This project started as a gap in Airship's core messaging system. At the time, customers could send a message immediately, schedule it once for later, or optimize delivery using machine learning — but they couldn't create a message that repeated on a regular cadence. If a team wanted a weekly, monthly, or yearly message, they had to manually recreate and manage multiple one-time schedules. At the same time, Airship was migrating customers from Accengage, a platform we had acquired that already supported recurring messages. Recurring scheduling became both a major customer need and a migration requirement. I worked across design, product, engineering, and program management to define and design the recurring scheduling experience inside Airship's existing delivery system.
Problem
Customers who needed recurring communication had no way to define a schedule once and rely on it over time. A daily reminder meant building a new scheduled message every day. A weekly message meant manually managing multiple future schedules. There was also no way to express patterns like "every Tuesday and Thursday." This created unnecessary manual work and cluttered dashboards with duplicate messages. On the business side, recurring scheduling was also required to migrate customers off Accengage and shut down the legacy platform.
Goals
The goal was straightforward: allow customers to create a message once and define a repeating cadence around it. That cadence needed to support daily, weekly, monthly, and yearly schedules, as well as more specific patterns like certain days of the week. From a platform perspective, the feature also needed to meet parity requirements for Accengage migration and work within the constraints of Airship's existing scheduling API.
Process
We began with a series of whiteboard sessions across design, engineering, and product. We reviewed the existing "send now," "schedule," and "optimize" delivery options in Airship and compared them to how Accengage handled recurring messages. We explored how start dates, time zones, end dates, and exclusion ranges worked in the legacy system and what was technically possible in Airship's API. One important constraint shaped the project early: the recurring scheduling API already existed, which meant this could not become a new automation product and instead had to live inside the existing scheduling system.
Exploring the Scheduling Model
I worked through how cadence would function across hourly, daily, weekly, bi-weekly, monthly, and yearly patterns. We mapped edge cases like the 31st of the month not occurring every month, how exclusions would prevent sends during certain hours or on certain dates, and how start and end dates would define the life of a recurring message. We also discussed how reporting would work when one message sends many times, ultimately aligning on a grouped reporting model so recurring performance could be viewed together.
Wireframes & Early Concepts
My first design approach treated recurring as an extension of one-time scheduling. A user would select "schedule" and then toggle recurring on. I built wireframes that exposed the different cadence options, time selection, exclusions, and end conditions inside that flow. This allowed us to visualize all of the required controls, but it also introduced complexity on top of an already dense scheduling experience.
Usability Testing
I built an interactive Figma prototype and ran usability sessions with customers using a realistic setup scenario. Participants were asked to imagine they already had a message configured and were now trying to make it recurring. A key finding was that users struggled to discover recurring when it was nested under one-time scheduling. There was also confusion around how often messages would actually fire over time. This feedback made it clear that recurring needed to be treated as its own step, not a hidden extension.
Solution
The final design moved recurring into its own clear path within the delivery flow. Users could explicitly choose that they were creating a recurring message and then define how often it would repeat. The experience supported hourly, daily, weekly, monthly, and yearly cadences, including specific day-of-week selection. Users could choose how delivery time behaved using Specify Time, Optimal Time, or Local Time. Start and end dates were made explicit, and ISO date formatting was clarified through UI and date pickers. Exclusions allowed users to prevent sends during specific hours, on specific dates, or across date ranges. A final Review screen summarized the full behavior of the recurring message before launch so users could confirm cadence, timing, and exclusions.
Impact
The recurring scheduling experience replaced the manual workaround customers had been using to manage repeating campaigns. Instead of recreating multiple scheduled messages, teams could define one recurring message and let it run over time. The feature also supported the migration of Accengage customers and allowed that legacy product to be retired. From a workflow perspective, it reduced setup time for customers and simplified how recurring communication was managed inside the platform.





