Multiplayer · In depth

FixedStepService

Route-scoped simulation clock that compensates for drift, prevents overlapping async ticks, bounds catch-up work, and reports dropped retained lag instead of replaying forever.

Explain it like I’m five

The simple mental model

FixedStepService is a metronome for game logic. Even when the computer hesitates, it advances the simulation in measured beats without starting two beats at once.

When it fits

When should I use it?

Use it for authoritative simulations or periodic work that needs stable step sizes, bounded catch-up, and explicit handling of excessive lag.

A practical API pattern

Follow the example

This pattern explains the named API. Application classes, credentials, and assets may need to be supplied; use a complete recipe for a runnable starting point.

Read this article as Markdown

JavaScript
const { FixedStepService } = require('redweb')

class Simulation extends FixedStepService {
  constructor() { super('simulation', 50, 3) }
  async onTick(stepMs, tick) {
    await game.update(stepMs, tick)
  }
}
  1. 1

    The service schedules ticks using the configured fixed interval.

  2. 2

    A slow asynchronous tick finishes before another begins.

  3. 3

    Limited catch-up reduces drift, while old excess lag is reported and discarded instead of causing an endless spiral.

Surface area

Methods and members

constructor(name, tickRateMs, maxCatchUpTicks?, maxRetainedLagMs?)

Creates a fixed-step route service with finite catch-up and retained-lag limits.

onTick(stepMs, tick)

Implement one simulation step. Async work never overlaps the next pulse.

onLagDropped(milliseconds)

Optional observability hook called when retained lag is deliberately discarded.