A few days ago, I decided to run a 5K. It’s one of those things with me that just never happened: I can hike uphill for hours, or swim non-stop for 2 kilometres, but just never run a 5K. Weird! As Claude suggested to me, I turned to App Store for a run training app, and found out… They’re all pretty bad.

And I don’t blame them. They are like dating apps: you get frustrated and leave if they don’t work; you leave happily if they do work! It’s just an awkward market.

As an Apple nerd, I knew WorkoutKit was a thing. I also knew that if I just wanted to run intervals, I could build a custom workout directly on my Apple Watch without any app at all. Put those two things together, I decided to build my own couch-to-5K training app. It’s minimally scoped, and I’ll just make it a free app.

This post is about my learning and experience with WorkoutKit.

The app — some quick context

My First 5K is a couch-to-5K training program structured as 24 workouts over 8 weeks. The workouts are all running and walking intervals — more walking early on, more running as the weeks progress, ending with a continuous 30-minute run in Week 8. The program itself is static; every user follows the same sequence.

My app does two things: it schedules that fixed program to the Apple Watch, and it shows the user their progress and upcoming workout. That’s it. WorkoutKit is essentially the entire implementation story.

What WorkoutKit is, and what it promises)

WorkoutKit, introduced at WWDC 2023 and updated at WWDC 2024, lets an iOS app suggest structured workout routines directly to the watchOS Workout app. You define the workout — goals, intervals, steps — and the framework handles scheduling and presentation. The Watch takes over from there, so there’s no watchOS app to build, no workout session management, no custom UI on the wrist.

The pitch in the WWDC sessions was compelling. Apple engineers talked about workout validation with detailed error feedback, reliable scheduling, and a framework built for third-party developers to feel like first-class citizens in the Workout app ecosystem.

In practice, it’s a little more complicated than that.

Good things first

I’ll give WorkoutKit this: the implementation lift is genuinely low.

Defining a structured workout — intervals, pacing goals, warmup and cooldown steps — is straightforward once you get your head around the data model. And because the Watch’s Workout app handles all the runtime UI, tracking, and metrics, I didn’t have to build any of that myself. For an app that’s fundamentally about delivering a workout program rather than building a custom workout experience, this is exactly the right trade-off.

For My First 5K, that made WorkoutKit a natural fit. The whole point was to stay out of the way and let the Watch do what it’s good at.

The frustrations

Validation does not exist

One of the things Apple demoed in the WWDC sessions was workout validation — the idea that the framework could tell you if something was wrong with a workout you’d constructed, with detailed error messages to help you fix it. In practice, this hasn’t matched the promise. The validation I encountered was surface-level at best. Don’t count on it to catch real issues.

For my app, the workout intervals are static. Had I used it for user-built workouts, I’d need to do more work validating workouts myself.

Silent failures

A recap on the Fitness app (iPhone) and the Workout app (Apple Watch):

  1. On iOS 18, if you don’t pair an Apple Watch, the Fitness app is not available to you on iPhone.
  2. On iOS 26, you can use the Fitness app without using an Apple Watch. Your iPhone is your hub of starting a fitness workout. You can use supported AirPods as vital metric sensors.
  3. On iOS 18 or iOS 26, if you pair an Apple Watch, you can use the Workout app or the Fitness app to start and record a workout. Your Apple Watch is your sensor, and you may view finished workouts on either device — they are in sync.

Take a guess on which device of the 3 above, do you think WorkoutKit is supported?

The answer: Only #3! Even for Device #2, where the Fitness app is available, the framework does nothing.

Take another guess on which device the WorkoutScheduler.isSupported class property returns false?

The answer: None of them! I have no idea which method may throw the errors in the documentation:

There is no error case for denied permissions, or for illegal workout intervals (e.g. a run that lasts -30 seconds, or a goal of reaching 0 kilocalories).

At the core, none of the WorkoutScheduler instance methods may throw. That means your invocation to schedule a workout always succeeds on paper, but nothing gets scheduled, silently.

The permissions UX

If a user denies WorkoutKit access when first prompted and later wants to grant it, the setting isn’t where you’d expect. It’s buried on the Apple Watch itself: Settings → Workout → Connected Apps, scrolled to the bottom. There’s no path through the iPhone’s Settings app, and it’s not somewhere most users would ever think to look. I’d love for Apple to expose this somewhere more accessible, or at least give developers a way to deep-link there.

I’ve looked up and down in the Fitness app on iPhone, but there is no permission control inside.

For a while, I wondered how a user might re-grant access on iOS 26, if they don’t have a paired Apple Watch. Turns out the framework simply won’t work for them at all. Ha!

Weird API design decisions

With the most glaring issues behind us, here are some quirks with the API design:

When scheduling a workout, the framework asks for a DateComponents. I guess the decision was so that schedules can survive time zone changes. But it invites questions:

  1. Can I schedule workouts for a certain month or day, but not for a specific day?
  2. Can I make a workout recurring every week on a certain work day?
  3. Can I schedule a workout to a specific time of the day?

The answers: No, no, and despite them doing exactly that in the WWDC session video, no, you cannot.

When querying or reading scheduled workouts, the framework provides no easy way to limit your query range. Your only bet is to fetch all workouts, sort or filter them yourself. My experience is that the list of workouts are in the order of when they were scheduled or last updated. But this is not documented and may change.

When marking complete or removing a scheduled workout, the framework API requires two parameters: the workout plan, and the date components. Where it should be providing: just the workout plan’s UUID. There is no documentation explaining what may happen if you remove or modify a workout plan for a date it wasn’t scheduled for.

There is no delegate or notification mechanism on data changes. You are best left with pull-to-refresh and refresh upon entering the app from the background.

The honest verdict

For a minimally scoped app like this one, WorkoutKit is absolutely the right tool. I’m not building a workout engine — I’m scheduling a fixed program to a device that already knows how to run workouts really well. WorkoutKit handles that job, and the low implementation cost made it practical to ship something focused and clean.

The catch is that you have to go in with calibrated expectations. The error handling you’d hope to get from the framework, you’ll need to build yourself. Verify your scheduling outcomes explicitly. Don’t assume silent means successful.

Once you account for that, the framework is sufficient — it just requires more defensive code than it should.

Where it gets harder to defend is the bigger picture. WorkoutKit was announced in 2023, updated in 2024, and has felt quiet since. The rough edges — silent failures, the buried permissions UX, the undocumented scheduling limitations — feel like things that should have been addressed by now. It’s a framework that gives the impression of having been shipped and then moved on from, without ever quite reaching the standard that was promised in those initial sessions.

That’s frustrating, because the core idea is good. I hope Apple picks it back up.

What I’d want Apple to fix

If someone on the WorkoutKit team ever reads indie dev blog posts:


As for me — I’m almost through Week 3. The app works, the Watch buzzes when it’s time to run, and I haven’t quit yet. That’s probably the best thing I can say about any tool.