Skip to main content
Migrate Already selling? Move your customers to Keylight without re-issuing a single key.
Keylight

Guide · Trials

Best free trial tools for Mac apps

A trial is a licensing state, not a countdown in UserDefaults. Here are the ways to run one in a Mac app, and which survive a reinstall, a new machine, and a determined tester.

Start Free

Updated July 2026

Ask most Mac developers where their trial “lives” and they’ll point at a line of code that checks a date. That’s the wrong mental model. A trial is not a countdown you bolt onto a build — it’s a licensing state, the same category of thing as “licensed” or “expired.” The moment you think of it that way, the question changes from “how do I check a date” to “where does that state actually live, and what happens when the app is reinstalled.”

That question matters because reinstalling is exactly what a curious or unwilling-to-pay user tries first. Delete the app, download it again, and a trial stored only on the device — a flag in UserDefaults, a timestamp in a plist — comes back looking brand new. A trial whose state lives somewhere else, tied to an account, a device identity, or a subscription record a server owns, does not reset just because the local copy of the app did.

This page ranks the real options for running a free trial in a Mac app, in order of how much control they actually give you over that reset — from a trial state your licensing server owns down to a plain local timer that’s more courtesy than control.

The best free trial tools for Mac apps

1. Keylight — best for a trial that survives a reinstall

The strongest pattern ties the trial to an identity your server tracks — an account, an email, or a device fingerprint recorded the first time the app runs — rather than to a value stored only inside the app’s own container. Because the state lives outside the app, reinstalling doesn’t quietly hand out a fresh evaluation window; the app resolves its trial status against the server the same way it would resolve a paid license.

Keylight is built around that pattern: trials are a first-class state in the same licensing state machine that handles paid and expired licenses, so the trial isn’t a bolt-on with its own rules, and a trial that resists casual reinstalling uses the same device identity tracking that caps activations on paid keys. Any licensing platform with server-side trial state can do a version of this — it isn’t unique to Keylight — but it is the difference between a trial your app can reason about and a date in a plist.

Worth saying plainly: this raises the cost of resetting a trial, it doesn’t make it impossible. A new machine, a fresh user account, or a different email is still a new trial to any system built this way.

2. Paddle and Lemon Squeezy built-in trials — best if you’re already routing payments through one

Both Paddle and Lemon Squeezy let you attach a free trial directly to a subscription price. Paddle’s checkout accepts a price with a trial_period and creates the resulting subscription in a trialing status it tracks server-side. Lemon Squeezy is a toggle on a subscription product — “Subscription has free trial?” — with the length set in days, weeks, months, or years. In both cases the trial is a real subscription record the processor owns, tied to the customer’s account and payment method, not a value stored on the Mac. Reinstalling the app doesn’t touch it. The tradeoff is that both are subscription mechanisms: they fit an app already selling on a recurring plan through one of these two providers, not a one-time-purchase app or one on a different processor.

3. StoreKit 2 introductory offers — best for a subscription app sold through the App Store

Apple lets you configure a free trial, a pay-as-you-go period, or a pay-up-front discount as an introductory offer on an auto-renewable subscription. Eligibility is enforced by Apple, not your app: per Apple’s own subscription documentation, a customer can redeem one introductory offer per subscription group, tracked against their account rather than anything stored on the device — so reinstalling the app or switching Macs doesn’t restore eligibility once it’s used. The catch is scope: this only exists for auto-renewable subscriptions sold through the App Store. It doesn’t apply to one-time-purchase pricing, and it isn’t available at all if you distribute outside the App Store with Developer ID.

4. Setapp as an alternative to running a trial at all — best if you don’t want to own the trial

Setapp sidesteps the whole problem by taking the trial off your plate entirely. New Setapp members get a free trial of the membership itself — currently seven days, per Setapp’s own support documentation — and during it they can open your app along with everything else in the catalog. You don’t write trial logic, host a licensing check, or handle the customer relationship around it; Setapp owns that end-to-end. In exchange, you give up direct pricing and the trial experience: Setapp’s membership model pays developers from a pool — 70% of each subscriber’s fee split across the apps they actually opened that period, weighted by a per-app pricing tier, with Setapp keeping the other 30% — or, if you’d rather sell your app individually through Setapp’s single-app distribution, a flat 75/25 split that can include a one-time purchase. Best for a developer who’d rather trade a slice of revenue and pricing control for having someone else run the trial and the checkout.

5. Time-limited builds — best for a trial with zero backend at all

A time-limited build simply refuses to run after a date compiled into the binary, checked against the system clock at launch. There’s no license server and, done right, no meaningful local state to tamper with — the expiry isn’t tied to when the app was installed, so reinstalling doesn’t buy a fresh window the way it does with a local timer. The tradeoff runs the other way: every evaluator who downloads a week after launch gets a week less trial than someone who downloaded on day one, and the whole scheme leans on the system clock, which a determined user can roll back, or on staying on an older download that hasn’t expired yet. It’s a reasonable choice for a short-lived beta or a preview build; it’s a poor fit for an ongoing product with a rolling stream of new evaluators.

6. DIY UserDefaults or Keychain timers — best only for near-zero-stakes utilities

The simplest option: record the first-launch date somewhere on disk and compare it to today. UserDefaults and plist files live inside the app’s own container, so deleting and reinstalling the app wipes them along with everything else — the trial resets itself for anyone who thinks to try. Keychain items behave differently: they’re commonly not removed when the app is deleted, which is why some apps lean on the Keychain for a firmer local timer than UserDefaults gives them. But that persistence is an implementation detail, not a documented or guaranteed behavior, it’s still scoped to that one machine, and it’s cleared by a fresh macOS user account, a full reset, or a trip to Keychain Access. Both variants stop a casual retry. Neither stands up to someone who’s actually looking.

Why a local timer is not a trial

Every mechanism in the bottom half of this list shares one property: the state that decides whether the trial is running lives only on the device. That’s the whole issue. Anything stored only on the device is something the user’s device ultimately controls — delete it, and the check has nothing to compare against, so it defaults back to “first launch.” A local timer isn’t a weaker trial; it’s a different thing wearing a trial’s clothes. It’s a courtesy that nudges an honest evaluator toward a decision. It was never a control that stops someone determined to keep using the app for free.

This isn’t an argument that every app needs a server-backed trial. It’s an honest tradeoff, and for a lot of apps the local-only version is the right call: it costs nothing to build, requires no backend, and does its actual job — reminding a genuine evaluator that the clock is running — perfectly well. The failure mode isn’t choosing a local timer. It’s calling it a control when it’s a courtesy, and being surprised when a screenshot of “how to reset any trial in three seconds” makes the rounds.

The same tension shows up one level up, in how a server-backed trial gets enforced. If the app refuses to run at all without contacting the server, a network hiccup locks out a paying evaluator who did nothing wrong — that’s a real cost, not a hypothetical one. If the app quietly falls back to “trial active” whenever it can’t reach the server, the enforcement is trivially bypassed by anyone willing to block outbound traffic. Neither failure mode is free; the honest version of “online validation” picks one of these tradeoffs on purpose instead of pretending the check is airtight either way.

How to choose

  • Building on a licensing layer already, or planning to → server-issued trial licenses. The trial and the paid license end up as states in the same system, and the reinstall problem is solved as a side effect.
  • Already selling subscriptions through Paddle or Lemon Squeezy → use the trial toggle built into the checkout you already have. Don’t build a second mechanism next to one you’re already paying for.
  • Subscription pricing, App Store only → StoreKit 2 introductory offers. It’s the native option, and it’s enforced by Apple against the account, not the device.
  • You’d rather not own the trial, the pricing, or the checkout at all → Setapp, with the tradeoff being revenue share and control.
  • A short beta or preview build, not an ongoing product → a time-limited build, accepting that early downloaders get a longer window than late ones.
  • A simple utility, one-time price, no backend you want to run → a local timer, and be honest with yourself that it’s a nudge, not a lock.

Where Keylight fits

Keylight treats the trial as one state in the same licensing system that handles paid licenses, expiry, and device activations — not a separate mechanism bolted on next to the real one. Set a trial length once, the SDK reports days remaining through the same state your app already switches on, and when the customer pays, Stripe’s webhook mints a signed license and the app moves cleanly from .trial to .licensed — no separate trial-key system to reconcile. If you want that trial to resist a plain reinstall, it plugs into the same device-activation tracking that enforces limits on paid keys, rather than trusting a value stored only on the customer’s Mac. The same dashboard tracks trial activations and devices that go quiet over 30 days, right alongside your paid ones — not a computed conversion rate, but the raw activation and churn counts a trial-to-paid decision actually needs.

Plans start at $19/month, with a free tier to test the full trial-to-paid flow before you ship.

Start licensing your app today

Drop in the Swift SDK, point it at your dashboard, and sell paid apps in under a minute. Free forever tier included.

Start Free