The closed page — part of core, the "Site closed" feature on the Website
access settings page (PhoenixKit.WebsiteAccess), where "Maintenance" and
"Under construction" are presets that switch it on with matching texts.
It shows a page (heading, message, countdown to a scheduled end) to all
non-admin users while admins and owners see the site. It is not a module:
no switch, no card on the Modules page, no permission and no settings page
of its own; only the mode itself is on or off, by hand or in a scheduled
window. The module names (PhoenixKit.Modules.Maintenance,
PhoenixKitWeb.Live.Modules.Maintenance.*) are kept so hosts that reference
them keep compiling.
Maintenance can be activated in two ways:
- Manual toggle: Immediately enables/disables maintenance mode
- Scheduled window: Set a start and end time for automatic activation
active?/0 returns true when either the manual toggle is on OR the current
time falls within a scheduled window.
Settings
The module uses the following settings stored in the database:
maintenance_enabled- Boolean to enable/disable maintenance mode manually (default: false)maintenance_header- Main heading text (default: "Maintenance Mode")maintenance_subtext- Descriptive subtext (default: "We'll be back soon")maintenance_scheduled_start- ISO 8601 UTC datetime for scheduled start (default: nil)maintenance_scheduled_end- ISO 8601 UTC datetime for scheduled end (default: nil)
Usage
# Check if maintenance mode is currently active (manual OR scheduled)
if PhoenixKit.Modules.Maintenance.active?() do
# Show maintenance page to non-admin users
end
# Enable/disable manually
PhoenixKit.Modules.Maintenance.enable_system()
PhoenixKit.Modules.Maintenance.disable_system()
# Schedule a maintenance window
PhoenixKit.Modules.Maintenance.update_schedule(
~U[2026-04-14 17:00:00Z],
~U[2026-04-14 18:00:00Z]
)
# Get module configuration
config = PhoenixKit.Modules.Maintenance.get_config()
Summary
Functions
Returns true if maintenance mode is currently active.
Broadcasts the current maintenance status.
validate_schedule/2 for a window saved over the stored one: a start that
has not changed is not checked against the clock. The window may be open
right now — its start has passed — and moving its end, or saving the form
it sits in, must not fail because it began.
Cleans up stale state when the scheduled end time has passed.
Clears the scheduled maintenance window. Broadcasts a PubSub event.
The stock heading — what get_header/0 answers when none was set.
The stock message — what get_subtext/0 answers when none was set.
Disables maintenance mode manually.
Enables maintenance mode manually.
Always true — kept for callers from the days maintenance was a module
with a switch. The maintenance_module_enabled setting is ignored.
Gets the full maintenance configuration. module_enabled is always true
and stays for callers that read it.
Gets the header text for the maintenance page.
Returns the scheduled end time as a DateTime, or nil.
Returns the scheduled start time as a DateTime, or nil.
Gets the subtext for the maintenance page.
Returns whether the manual maintenance toggle is on.
Returns true if the current time is past the scheduled end time.
Returns true if the current time is past the scheduled start time.
Returns the PubSub topic for maintenance status changes.
Whether two times fall in the same minute — what a datetime-local field can tell apart.
Returns the number of seconds until maintenance ends, or nil if unknown.
Turns maintenance mode on or off. opts carry the settings history's
actor and source (actor_uuid:, source:).
Subscribes the calling process to maintenance status change events.
Updates the header text for the maintenance page.
Sets a scheduled maintenance window.
Updates the subtext for the maintenance page.
Validates a proposed maintenance schedule.
Returns true if a scheduled maintenance window is currently active.
Functions
Returns true if maintenance mode is currently active.
The main function used to check maintenance status. Logic:
- If a scheduled end time is set and has passed → off (auto-turn-off)
- If the manual toggle is on → on
- If a scheduled start time is set and has passed → on (auto-turn-on)
- Otherwise → off
Schedule configurations:
- Start only: activates at start time, stays on until manually disabled
- End only: manual toggle works, but auto-disables at end time
- Start + End: active during the window
- Neither: just the manual toggle
Examples
iex> PhoenixKit.Modules.Maintenance.active?()
false
Broadcasts the current maintenance status.
Sends {:maintenance_status_changed, %{active: boolean}} to all subscribers.
validate_schedule/2 for a window saved over the stored one: a start that
has not changed is not checked against the clock. The window may be open
right now — its start has passed — and moving its end, or saving the form
it sits in, must not fail because it began.
Cleans up stale state when the scheduled end time has passed.
Disables the manual toggle and clears the schedule, then broadcasts so any connected users get their layout restored.
Returns true if cleanup was performed, false if nothing needed cleaning.
Safe to call repeatedly — it's a no-op when there's nothing stale.
Clears the scheduled maintenance window. Broadcasts a PubSub event.
The stock heading — what get_header/0 answers when none was set.
The stock message — what get_subtext/0 answers when none was set.
Disables maintenance mode manually.
When disabled, all users can access the site normally. Also clears both scheduled start and end times so stale schedule values don't re-activate maintenance or leave surprise auto-off signals for later re-enables. Broadcasts a PubSub event so the maintenance layout is removed.
Enables maintenance mode manually.
When enabled, all non-admin users will see the maintenance page. Broadcasts a PubSub event so LiveViews can react in real time.
Always true — kept for callers from the days maintenance was a module
with a switch. The maintenance_module_enabled setting is ignored.
Gets the full maintenance configuration. module_enabled is always true
and stays for callers that read it.
Gets the header text for the maintenance page.
Returns the scheduled end time as a DateTime, or nil.
Returns the scheduled start time as a DateTime, or nil.
Gets the subtext for the maintenance page.
Returns whether the manual maintenance toggle is on.
Returns true if the current time is past the scheduled end time.
When true, maintenance is forced off regardless of other settings. Used as an auto-turn-off mechanism.
Returns true if the current time is past the scheduled start time.
Used for start-only schedules (no end time) or as the "on" condition in a start+end window.
Returns the PubSub topic for maintenance status changes.
Whether two times fall in the same minute — what a datetime-local field can tell apart.
Returns the number of seconds until maintenance ends, or nil if unknown.
Used for the Retry-After HTTP header and countdown timer. Returns nil if maintenance is manually enabled without a scheduled end, or if maintenance is not active.
Turns maintenance mode on or off. opts carry the settings history's
actor and source (actor_uuid:, source:).
Subscribes the calling process to maintenance status change events.
Updates the header text for the maintenance page.
Sets a scheduled maintenance window.
Either or both times can be provided:
- Start only: maintenance activates at start, stays on until manually disabled
- End only: maintenance auto-disables at end time
- Both: maintenance is active between start and end
Validates the schedule via validate_schedule/2 before writing.
Times are stored as ISO 8601 UTC strings. Pass nil to clear a field.
Broadcasts a PubSub event on success.
Returns :ok on success or {:error, atom} on validation/DB failure.
Updates the subtext for the maintenance page.
Validates a proposed maintenance schedule.
Rules:
- At least one of start or end must be provided
- Start (if set) must be in the future
- End (if set) must be in the future
- If both are set, end must be strictly after start
A small tolerance (60 seconds) is applied to "in the future" checks to handle datetime-local inputs which only have minute precision and minor clock drift between client and server.
Returns :ok or {:error, atom} where atom is one of:
:empty— neither start nor end provided:start_in_past:end_in_past:end_before_start— end is before or equal to start:too_far_future— date is more than one year in the future
Returns true if a scheduled maintenance window is currently active.
Handles three schedule configurations:
- Start + End: active between start and end times
- Start only: active once past start, stays on indefinitely
- End only: returns false (end-only acts as auto-off for the manual toggle)