For AI agents: the complete documentation index is available at https://open-spaced-repetition.github.io/ts-fsrs/llms.txt, the full documentation bundle is available at https://open-spaced-repetition.github.io/ts-fsrs/llms-full.txt, and this page is available as Markdown at https://open-spaced-repetition.github.io/ts-fsrs/guide/scheduler/default-scheduler.md.

DefaultScheduler

DefaultScheduler is an async factory that returns a ready scheduler instance. It creates a model (FSRS-7 by default) with dateChrono and the standard scheduling policies, so the only thing you configure is its options. Internally it is the same definition-and-instance machinery as a custom defineScheduler — the preset is just a convenient assembly.

Options

When upgrading from FSRS-3~6 to FSRS-7, omit weights to use FSRS-7 defaults or supply weights trained for FSRS-7. Replaying history rebuilds card state; it does not convert legacy weights.

FSRS-7 cards include stabilityFast as well as stability and difficulty. Rebuild legacy FSRS-3~6 memory states by replaying review history with Reschedule; parameter migration does not migrate card state. Do not seed an evolved fast trace with 0.8 * stability. The preset enables fractional days for FSRS-7, and enableShortTerm: false only disables explicit learning steps, not the model's fast trace.

For cost-adaptive retention, create a custom definition with schedulerCostAdrMiddleware in place of schedulerDesiredRetentionMiddleware. Cost ADR is not a DefaultScheduler option.

scheduler.nextInterval(memoryState, desiredRetention, { card, grade, elapsedDays }) queries the interval for an already computed post-rating state. It runs handlers.nextInterval without advancing the card or chrono; put shared interval policies in that hook.

OptionDefaultPurpose
version'FSRS-7'Selects the FSRS model: 'FSRS-3', 'FSRS-4', 'FSRS-4.5', 'FSRS-5', 'FSRS-6', or 'FSRS-7'. FSRS-7 cannot migrate legacy FSRS-3~6 weights.
weightspreset weightsOptional trained weights; omit to use the preset's defaults for the selected version. FSRS-7 requires exactly 34 FSRS-7 weights; supplying legacy weights throws during scheduler construction.
desiredRetention0.9Target retention applied before interval calculation.
enableShortTermtrueEnables learning and relearning steps.
learningSteps['1m', '10m']Learning steps applied when enableShortTerm is on.
relearningSteps['10m']Relearning steps applied when enableShortTerm is on.
graduatingInterval1Shortest interval, in days, for a card in Review. A card which has a shorter interval after a review will stay in Learning/Relearning. When steps are configured, finishing them and rating a Review card Hard, Good, or Easy will result in at least this interval.
allowModelOverrideFSRS-7: true; other versions: falseUses the model interval instead of the current step when the model interval is longer. Again is capped at graduatingInterval; Hard and Good graduate early once the interval reaches graduatingInterval.
enableFuzzfalseSpreads intervals for variety when enabled.
maximumInterval36500Upper bound on the interval in days.
clearStatsOnForgettrueWhether forget clears reps and lapses.

DefaultScheduler always uses dateChrono and applies the standard policies in the order described on the Middleware page: desired retention, fuzzing, statistics, scheduled days, learning steps, maximum interval, then monotonic interval. Choosing version changes the model and its parameters, not this policy set.

import { 
function DefaultScheduler<Version extends DefaultSchedulerVersion = "FSRS-7">(options?: DefaultSchedulerOptions<Version>): Promise<DefaultScheduler<Version>>
type DefaultScheduler<Version extends DefaultSchedulerVersion = "FSRS-7"> = (Version extends "FSRS-7" ? Omit<SchedulerCore<SchedulerCoreEnv<SchedulerEnvFor<FSRS7DefaultSchedulerModel, Chrono<{
    readonly time: SRSSchema<{
        input: Date;
        output: Date;
    }>;
    readonly config: SRSSchema<{
        input: {
            readonly fractionalDays?: boolean | undefined;
        };
        output: {
            readonly fractionalDays: boolean;
        };
    }>;
    readonly fields: {
        readonly card: SRSSchema<{
            input: {
                dueAt: Date;
                lastReviewAt?: (Date | null) | undefined;
            };
            output: {
                dueAt: Date;
                lastReviewAt: Date | null;
            };
        }>;
        readonly revlog: SRSSchema<{
            input: {
                dueAt: Date;
                lastReviewAt?: (Date | null) | undefined;
                reviewTime: Date;
            };
            output: {
                dueAt: Date;
                lastReviewAt: Date | null;
                reviewTime: Date;
            };
        }>;
    };
}>, readonly [...]>>, ModelCore<...>, ChronoCore<...>>, "definition"> : Omit<...> & {
    ...;
}) & {
    ...;
}
DefaultScheduler
,
type Rating = 0 | 1 | 2 | 3 | 4
const Rating: Readonly<{
    readonly Manual: 0;
    readonly Again: 1;
    readonly Hard: 2;
    readonly Good: 3;
    readonly Easy: 4;
}>
Rating
} from 'ts-fsrs'
const now = new Date('2026-01-01T00:00:00.000Z') const
const scheduler: DefaultScheduler<"FSRS-7">
scheduler
= await
DefaultScheduler<"FSRS-7">(options?: DefaultSchedulerOptions<"FSRS-7"> | undefined): Promise<DefaultScheduler<"FSRS-7">>
DefaultScheduler
({
DefaultSchedulerOptions<"FSRS-7">.version?: "FSRS-7" | undefined

FSRS model and parameter migration version; defaults to FSRS-7.

version
: 'FSRS-7',
DefaultSchedulerOptions<Version extends DefaultSchedulerVersion = DefaultSchedulerVersion>.desiredRetention?: number | undefined
desiredRetention
: 0.9,
DefaultSchedulerOptions<Version extends DefaultSchedulerVersion = DefaultSchedulerVersion>.enableShortTerm?: boolean | undefined

Enable explicit learning steps. FSRS-7 always retains its intrinsic fast trace.

enableShortTerm
: true,
DefaultSchedulerOptions<"FSRS-7">.learningSteps?: readonly (`${number}d` | `${number}m` | `${number}h`)[] | undefined

Defaults to ['1m', '10m'].

learningSteps
: ['1m', '10m'],
DefaultSchedulerOptions<"FSRS-7">.relearningSteps?: readonly (`${number}d` | `${number}m` | `${number}h`)[] | undefined

Defaults to ['10m'].

relearningSteps
: ['10m'],
DefaultSchedulerOptions<Version extends DefaultSchedulerVersion = DefaultSchedulerVersion>.enableFuzz?: boolean | undefined
enableFuzz
: false,
DefaultSchedulerOptions<Version extends DefaultSchedulerVersion = DefaultSchedulerVersion>.maximumInterval?: number | undefined
maximumInterval
: 36_500,
}) const
const card: {
    cardId: string | number;
    stabilityFast: number;
    stability: number;
    difficulty: number;
    dueAt: Date;
    lastReviewAt: Date | null;
    reps: number;
    lapses: number;
    scheduledDays: number;
    learningStep: number;
    state: State;
    scheduleStatus: "review" | "new" | "learning";
}
card
=
const scheduler: DefaultScheduler<"FSRS-7">
scheduler
.
newCard: (options?: ({
    readonly cardId?: string | number | undefined;
} & {
    readonly now?: Date | undefined;
}) | undefined) => {
    cardId: string | number;
    stabilityFast: number;
    stability: number;
    difficulty: number;
    dueAt: Date;
    lastReviewAt: Date | null;
    reps: number;
    lapses: number;
    scheduledDays: number;
    learningStep: number;
    state: State;
    scheduleStatus: "review" | "new" | "learning";
}
newCard
({ cardId: 'quick-start', now })
const
const result: {
    card: {
        cardId: string | number;
        stabilityFast: number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        reps: number;
        lapses: number;
        scheduledDays: number;
        learningStep: number;
        state: State;
        scheduleStatus: "review" | "new" | "learning";
    };
    revlog: {
        cardId: string | number;
        stabilityFast: number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        scheduledDays: number;
        learningStep: number;
        reviewTime: Date;
        state: State;
        scheduleStatus: "review" | "new" | "learning";
        rating: Grade;
    };
}
result
=
const scheduler: DefaultScheduler<"FSRS-7">
scheduler
.
review: (input: {
    readonly card: Readonly<Omit<Readonly<{
        stabilityFast: number;
        stability: number;
        difficulty: number;
    } & {
        dueAt: Date;
        lastReviewAt: Date | null;
    } & {
        readonly cardId: string | number;
        readonly reps: number;
        readonly lapses: number;
        readonly scheduledDays: number;
        readonly learningStep?: number | undefined;
    } & SchedulerCoreFields$1<"review" | "new" | "learning">>, keyof SchedulerCoreFields$1<"review" | "new" | "learning">> & SchedulerCoreFields$1<"review" | "new" | "learning">>;
    readonly grade: Grade;
    readonly now?: Date | undefined;
}) => {
    ...;
}
review
({ card, grade:
const Rating: Readonly<{
    readonly Manual: 0;
    readonly Again: 1;
    readonly Hard: 2;
    readonly Good: 3;
    readonly Easy: 4;
}>
Rating
.Good, now })
console.log( JSON.stringify( { state:
const result: {
    card: {
        cardId: string | number;
        stabilityFast: number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        reps: number;
        lapses: number;
        scheduledDays: number;
        learningStep: number;
        state: State;
        scheduleStatus: "review" | "new" | "learning";
    };
    revlog: {
        cardId: string | number;
        stabilityFast: number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        scheduledDays: number;
        learningStep: number;
        reviewTime: Date;
        state: State;
        scheduleStatus: "review" | "new" | "learning";
        rating: Grade;
    };
}
result
.
card: {
    cardId: string | number;
    stabilityFast: number;
    stability: number;
    difficulty: number;
    dueAt: Date;
    lastReviewAt: Date | null;
    reps: number;
    lapses: number;
    scheduledDays: number;
    learningStep: number;
    state: State;
    scheduleStatus: "review" | "new" | "learning";
}
card
.state,
dueAt:
const result: {
    card: {
        cardId: string | number;
        stabilityFast: number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        reps: number;
        lapses: number;
        scheduledDays: number;
        learningStep: number;
        state: State;
        scheduleStatus: "review" | "new" | "learning";
    };
    revlog: {
        cardId: string | number;
        stabilityFast: number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        scheduledDays: number;
        learningStep: number;
        reviewTime: Date;
        state: State;
        scheduleStatus: "review" | "new" | "learning";
        rating: Grade;
    };
}
result
.
card: {
    cardId: string | number;
    stabilityFast: number;
    stability: number;
    difficulty: number;
    dueAt: Date;
    lastReviewAt: Date | null;
    reps: number;
    lapses: number;
    scheduledDays: number;
    learningStep: number;
    state: State;
    scheduleStatus: "review" | "new" | "learning";
}
card
.dueAt,
stability:
const result: {
    card: {
        cardId: string | number;
        stabilityFast: number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        reps: number;
        lapses: number;
        scheduledDays: number;
        learningStep: number;
        state: State;
        scheduleStatus: "review" | "new" | "learning";
    };
    revlog: {
        cardId: string | number;
        stabilityFast: number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        scheduledDays: number;
        learningStep: number;
        reviewTime: Date;
        state: State;
        scheduleStatus: "review" | "new" | "learning";
        rating: Grade;
    };
}
result
.
card: {
    cardId: string | number;
    stabilityFast: number;
    stability: number;
    difficulty: number;
    dueAt: Date;
    lastReviewAt: Date | null;
    reps: number;
    lapses: number;
    scheduledDays: number;
    learningStep: number;
    state: State;
    scheduleStatus: "review" | "new" | "learning";
}
card
.stability,
stabilityFast:
const result: {
    card: {
        cardId: string | number;
        stabilityFast: number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        reps: number;
        lapses: number;
        scheduledDays: number;
        learningStep: number;
        state: State;
        scheduleStatus: "review" | "new" | "learning";
    };
    revlog: {
        cardId: string | number;
        stabilityFast: number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        scheduledDays: number;
        learningStep: number;
        reviewTime: Date;
        state: State;
        scheduleStatus: "review" | "new" | "learning";
        rating: Grade;
    };
}
result
.
card: {
    cardId: string | number;
    stabilityFast: number;
    stability: number;
    difficulty: number;
    dueAt: Date;
    lastReviewAt: Date | null;
    reps: number;
    lapses: number;
    scheduledDays: number;
    learningStep: number;
    state: State;
    scheduleStatus: "review" | "new" | "learning";
}
card
.stabilityFast,
difficulty:
const result: {
    card: {
        cardId: string | number;
        stabilityFast: number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        reps: number;
        lapses: number;
        scheduledDays: number;
        learningStep: number;
        state: State;
        scheduleStatus: "review" | "new" | "learning";
    };
    revlog: {
        cardId: string | number;
        stabilityFast: number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        scheduledDays: number;
        learningStep: number;
        reviewTime: Date;
        state: State;
        scheduleStatus: "review" | "new" | "learning";
        rating: Grade;
    };
}
result
.
card: {
    cardId: string | number;
    stabilityFast: number;
    stability: number;
    difficulty: number;
    dueAt: Date;
    lastReviewAt: Date | null;
    reps: number;
    lapses: number;
    scheduledDays: number;
    learningStep: number;
    state: State;
    scheduleStatus: "review" | "new" | "learning";
}
card
.difficulty,
rating:
const result: {
    card: {
        cardId: string | number;
        stabilityFast: number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        reps: number;
        lapses: number;
        scheduledDays: number;
        learningStep: number;
        state: State;
        scheduleStatus: "review" | "new" | "learning";
    };
    revlog: {
        cardId: string | number;
        stabilityFast: number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        scheduledDays: number;
        learningStep: number;
        reviewTime: Date;
        state: State;
        scheduleStatus: "review" | "new" | "learning";
        rating: Grade;
    };
}
result
.
revlog: {
    cardId: string | number;
    stabilityFast: number;
    stability: number;
    difficulty: number;
    dueAt: Date;
    lastReviewAt: Date | null;
    scheduledDays: number;
    learningStep: number;
    reviewTime: Date;
    state: State;
    scheduleStatus: "review" | "new" | "learning";
    rating: Grade;
}
revlog
.rating,
}, null, 2 ) )

The factory is async, so await DefaultScheduler(...) before using the returned instance. The example makes the common defaults explicit: version, desiredRetention, learning and relearning steps, fuzzing, and maximumInterval. Omit weights to use the preset for the selected FSRS version.

Preset or custom definition

Reach for DefaultScheduler when the default FSRS model, dateChrono, and the standard policy set fit your product — it is the fastest correct start. Reach for defineScheduler when you need a different model or chronology, add or remove policies, or expose a configuration you validate per user. Both end in the same scheduler instance API (newCard, review, rollback, preview, and forget). See Scheduler overview for the definition-and-instance model.