When DSA Solved Our AWS Scaling Problem
In the age of AI, it feels like DSA is slowly disappearing from day-to-day development.
You can ask an AI to generate a queue, configure an AWS service, or write a retry mechanism in seconds.
But there is one thing AI cannot remove from engineering:
Constraints.
And when constraints appear, DSA suddenly becomes relevant again.
At our startup, we often solve problems in a scalable way. But scalability doesn't always mean adding another AWS service. Sometimes, the solution is simply using the existing components differently.
You usually don't recognize a DSA concept in a real-world system until someone asks:
"Why are we doing it this way?"
That question led us to a surprisingly simple solution to an AWS scheduling problem.
The Problem: We Were Running Out of Schedules
Imagine we have a large number of jobs.
Each job can fail and needs to be retried on subsequent days:
Parent Job
ā
āāā Retry 1 ā +1 day
āāā Retry 2 ā +2 days
āāā Retry 3 ā +3 days
Initially, this seems straightforward.
We can simply create an EventBridge schedule for every retry.
But then scale enters the picture.
We encountered a situation where, for every 6,000 jobs, we needed to create 3 separate EventBridge schedules.
That means:
6,000 jobs
Ć
3 retry schedules
=
18,000 schedules
Now imagine increasing the workload.
What happens if we have 10,000 jobs?
10,000 jobs
Ć
3 retries
=
30,000 schedules
And what if this keeps growing?
We eventually run into EventBridge scheduling limits.
The obvious solution might be:
"Let's add another AWS component."
But our senior asked a different question:
"Can we solve this using a sliding window?"
That was the interesting part.
First, What Is a Sliding Window?
A sliding window is a technique where we don't process the entire dataset at once.
Instead, we maintain a smaller active window and continuously move it forward.
For example, imagine these jobs:
Day 1 Day 2 Day 3 Day 4 Day 5 Day 6 Day 7
āāāāāāāāā¼āāāāāāāā¼āāāāāāāā¼āāāāāāāā¼āāāāāāāā¼āāāāāāāā¼āāāāāāāā¤
[āāāāāāāāāāāā Window āāāāāāāāāāāā]
As time moves forward:
Before:
Day 1 Day 2 Day 3 Day 4 Day 5 Day 6 Day 7
[āāāāāāāā Window āāāāāāāā]
After:
Day 1 Day 2 Day 3 Day 4 Day 5 Day 6 Day 7
[āāāāāāāā Window āāāāāāāā]
The important idea is:
We don't need to keep scheduling everything forever.
We only care about jobs relevant to the current time window.
That observation changes how we think about the EventBridge problem.
What If We Don't Schedule Every Retry?
This was the key idea.
Instead of asking:
"When should this retry happen?"
and creating an EventBridge schedule for that future date...
we ask:
"Which retries are supposed to happen today?"
That small change removes the need to schedule every future retry individually.
The Original Approach
Let's say today is August 18.
A parent job runs today.
Its retries are:
August 18
ā
āāā Retry 1 ā August 19
āāā Retry 2 ā August 20
āāā Retry 3 ā August 21
The traditional approach is:
EventBridge
ā
āāāāāāāāāāāā¼āāāāāāāāāāā
ā¼ ā¼ ā¼
Aug 19 Aug 20 Aug 21
Retry 1 Retry 2 Retry 3
For every parent job, we create future schedules.
This is where the number of schedules grows rapidly.
The Sliding Window Approach
Now let's change the perspective.
Instead of scheduling:
Retry 1 ā tomorrow
Retry 2 ā day after tomorrow
Retry 3 ā three days later
we maintain a daily execution window.
Every day, we ask:
"Which existing parent jobs have a retry due today?"
Then we execute those retries.
TODAY
ā
ā¼
āāāāāāāāāāāāāāāāāāā
ā Sliding ā
ā Window ā
āāāāāāāāāā¬āāāāāāāāā
ā
āāāāāāāāāāāāāāā¼āāāāāāāāāāāāāā
ā¼ ā¼ ā¼
Retry 1 Retry 2 Retry 3
due today due today due today
EventBridge no longer needs to know about every individual retry.
It only needs to trigger the parent job.
But What About Jobs From Previous Days?
This is where the idea becomes interesting.
Suppose a parent job ran 3 days ago.
Let's say:
Parent Job
August 15
ā
āāā Retry 1 ā August 16
āāā Retry 2 ā August 17
āāā Retry 3 ā August 18
Today is August 18.
The third retry is due today.
Under the traditional approach, we would have created a schedule on August 15 for the retry that should execute on August 18.
But we don't need to do that anymore.
Instead, today's sliding window discovers it.
August 15 August 16 August 17 August 18
Parent Job Retry 1 Retry 2 Retry 3
ā ā ā ā
āāāāāāāāāāāāāāāāāā“āāāāāāāāāāāāāāāāā“āāāāāāāāāāāāāāāāā
ā²
ā
TODAY
The system simply asks:
"What retries are due on August 18?"
And finds:
Parent Job: August 15
Retry: 3
Due: August 18
Then it executes it.
The Trick
This is the entire trick:
Don't schedule the future retries.
Instead Conceptually:
āāāāāāāāāāāāāāāāāāāāāāā
ā Daily Trigger ā
āāāāāāāāāāāā¬āāāāāāāāāāā
ā
ā¼
āāāāāāāāāāāāāāāāāāāāāāā
ā Current Time ā
ā Window ā
āāāāāāāāāāāā¬āāāāāāāāāāā
ā
ā¼
āāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā Find retries due today ā
āāāāāāāāāāāāāā¬āāāāāāāāāāāāāā
ā
āāāāāāāāāāā“āāāāāāāāāā
ā¼ ā¼
Retry due Not due
ā ā
ā¼ ā¼
Execute Ignore
Why This Scales Better
The important difference is what we are scheduling.
Number of schedules grows
with the number of jobs
Now the number of EventBridge schedules is no longer directly proportional to:
Number of Jobs Ć Number of Retries
Instead, EventBridge becomes the mechanism that wakes up the scheduler/processor, while the application determines which work actually needs to happen.
The Bigger Lesson
The interesting part of this problem wasn't really EventBridge.
It was recognizing that we were using EventBridge to solve a problem that didn't necessarily belong there.
We initially thought:
"We need to schedule millions of future events."
The better question was:
"Do we actually need to schedule millions of future events?"
And the answer was no.
We only needed to know:
"What needs to happen today?"
That is where a simple DSA concept like sliding window becomes a practical system-design technique.
DSA Is Not Dead
This is why I don't think DSA is disappearing from software engineering.
Sometimes the answer is a sophisticated distributed system.
And sometimes...
it's a sliding window.
The important skill isn't memorizing DSA patterns.










