Skip to main content

Postinstall messages in Joomla

18 June 2026

Right after you install Joomla, or just after a big update, you sometimes see a short message in the administrator: "We changed this setting, here is what you should know." It looks like a small notice, but it is a real core component doing a real job. That component is com_postinstall, and it is how Joomla and its extensions talk to you at the exact moment a change happens.

This article explains how the Joomla Post-installation Messages component really works. It covers the basics for website owners and editors, the day-to-day screen for administrators, and the technical details for developers: the message types, the states, the database table, the display pipeline, RAD paths, and how to create your own messages.

The quiet component that turns "we changed something important" into a message you can read, act on, and dismiss.

The goal is simple: help you understand com_postinstall well enough to read its messages with confidence and, if you build extensions, send your own.

1. The Basics

1.1 What com_postinstall Is

com_postinstall is a small core component that shows post-installation and upgrade messages. When Joomla itself, or one of your extensions, needs to tell you something right after an install or update, it stores a message and com_postinstall displays it. The official description is short and exact: "Displays post-installation and post-upgrade messages for Joomla and its extensions."

It is an administrator-only component. It has no frontend, no articles, and no public URL. It exists to deliver one-time notices to the people who run the site.

If you ever saw a Joomla notice like "Your old TinyMCE setting changed, click here to review it," that was com_postinstall.

1.2 Where to Find It

The screen lives under the System menu in the administrator:

System
 └─ Manage
     └─ Post-installation Messages

The full title of the page is Post-installation and Upgrade Messages. Its URL is index.php?option=com_postinstall in the administrator. You can also reach it from the System Dashboard, where a small notification panel shows how many messages wait for you.

1.3 Why It Exists

Some changes cannot be applied silently. A new Joomla version might add a security setting that you must turn on yourself, or change a default that affects your content. A normal email or changelog is easy to miss. A message that sits in the administrator, with a button that performs the change for you, is much harder to ignore. That is the whole point of com_postinstall: the right notice, in the right place, at the right time.

Back to top

2. The Anatomy of a Message

Each message is shown as a card. A typical card has four parts:

PartWhat it is
Title A short headline, shown as a heading on the card.
Since version A small line, "Since version X", telling you which version introduced the message.
Description The body text that explains the change and what you should do.
Action button An optional button. It either opens a link or runs a task. Plain notices have no button.

Next to the action button, administrators also see two small buttons to manage the message itself:

  • Hide this message - removes the message from the list. You are done with it.
  • Archive - moves the message to an "archived" state. It is no longer active, but you can read it again later.

Every text you read on the card comes from a language key, not from fixed text. The title, the description, and the button label are all keys like COM_FOOBAR_POSTINSTALL_MESSAGEONE_TITLE. Joomla loads the extension's language file and translates the key. This is why messages appear in your own language when a translation exists.

Back to top

3. The Three Message Types

Every message has a type. The type decides whether there is a button and what the button does. There are exactly three types.

TypeButtonWhat happens
message None A plain informative notice. You read it and dismiss it.
link Yes The button opens a URL, for example a settings page inside Joomla.
action Yes The button runs a PHP function that performs a change for you.

3.1 message

The simplest type. There is no action button, only the title, the description, and the management buttons. Use it when you only need to inform.

The action button sends you to a URL. The URL is stored with the message. A common example is a button that opens a specific Options screen: index.php?option=com_foobar&view=tools&task=installSampleData. The user clicks, Joomla redirects, and the user finishes the change there.

3.3 action

The most powerful type. The button calls a PHP function inside the extension. Joomla loads a file, runs a named function, and the function does the work. This is how a message can say "Click here to fix this for you" and actually apply the fix when clicked.

Back to top

4. Daily Use for Administrators

4.1 Reading and Clearing Messages

Open System → Manage → Post-installation Messages. Read each card. If a card has an action button, decide whether to use it. When you are finished with a message, click Hide this message. When the list is empty, Joomla shows a friendly note: "You have read all the messages."

4.2 The Extension Filter

At the top of the page there is a dropdown labelled Showing messages for. By default the list shows messages for the Joomla core (the "Joomla! files" extension). If other extensions have left messages, you can pick them from this dropdown to switch the list. When only the core has messages, the dropdown is hidden to keep the screen clean.

4.3 Hide All Messages

The toolbar has a Hide All Messages button. It hides every message for the currently selected extension in one click. Use it when you have read everything and want a clean dashboard.

4.4 Reset Messages

Hidden messages are not deleted, only marked as hidden. If you ever need them back, the empty-state screen offers a Reset Messages button. It re-enables every message for the selected extension, so they all return to the active list. This is useful when you hid a message too fast and want to read it again.

4.5 Read Again

An archived message is not gone either. On its card you will see a Read Again button (an archived message can be republished). Click it and the message returns to the active list. So you have two soft ways to remove a message (Hide and Archive) and two ways to bring messages back (Reset and Read Again).

Back to top

5. Message States: Published, Hidden, Archived

Behind the buttons there is a single column, enabled, that holds the state of every message. It has three values.

enabledStateMeaning
1 Published Active. The message shows as a normal card with its action button.
2 Archived Set aside. Shown only as a small card with a "Read Again" button.
0 Hidden Dismissed. Not shown at all, but still stored in the database.

The list screen loads messages where enabled is 1 or 2, so hidden messages (0) never appear. The notification count on the System Dashboard, however, counts only the 1 (published) messages, because those are the ones that still need your attention.

The buttons simply change this one value: Hide sets it to 0, Archive sets it to 2, Read Again and Reset set it back to 1.

Back to top

6. Under the Hood: The Database Table

All messages live in one table, #__postinstall_messages. (The #__ prefix becomes your real table prefix, for example jos_postinstall_messages.) Each row is one message. These are the columns that matter.

ColumnPurpose
postinstall_message_id Primary key, the unique id of the message.
extension_id Which extension owns the message (a row in #__extensions).
type One of message, link, or action.
title_key Language key for the title.
description_key Language key for the body text.
action_key Language key for the button label (not used by message).
language_extension Which extension holds the language keys, for example com_foobar.
language_client_id Load frontend (0) or backend (1) language files.
action_file RAD path to the PHP file for an action message.
action For link: the URL. For action: the PHP function name.
condition_file RAD path to a PHP file that decides if the message should show.
condition_method The PHP function that returns true or false to show or hide the message.
version_introduced The version that first showed this message ("Since version X").
enabled State: 1 published, 2 archived, 0 hidden.

Notice that the table stores keys and paths, never the final text. The real words are resolved later from language files. This keeps messages translatable and small.

Back to top

7. Under the Hood: How Messages Are Displayed

com_postinstall is a standard Model-View-Controller (MVC) component. When you open the screen, the flow is straightforward.

  1. The view asks the model (MessagesModel) for the messages of the selected extension.
  2. The model reads the rows from #__postinstall_messages where enabled is 1 or 2.
  3. The model post-processes the list: it loads the right language files and runs each message's display condition.
  4. The template renders each surviving message as a card.

7.1 Conditions Decide Visibility

A message can carry a condition_file and a condition_method. During post-processing the model includes the file and calls the function. If the function returns false, the message is dropped from the list before it is ever shown. This is how a message can appear only when it is relevant, for example "only show this if the old setting is still active." Once the user fixes the problem, the condition returns false and the message quietly disappears.

7.2 Caching

The model caches its results in the com_postinstall cache group, because reading and evaluating messages on every page load would be wasteful. Whenever a message changes state (hide, archive, republish, reset), the component clears this cache so the list and the dashboard count stay correct.

7.3 Language Loading

Before rendering, the model loads each message's language extension, using the frontend or backend path based on language_client_id. This is why a message from com_foobar shows its own translated title and description, even though com_postinstall knows nothing about that extension's wording.

Back to top

8. RAD Paths, Conditions, and Actions

8.1 What a RAD Path Is

The action_file and condition_file columns do not store full disk paths. They store short RAD paths with a prefix that Joomla expands at runtime. There are two prefixes.

PrefixExpands toExample
site:// The site root (JPATH_ROOT) site://components/com_foobar/postinstall.php
admin:// The administrator folder (JPATH_ADMINISTRATOR) admin://components/com_foobar/postinstall.php

A small helper expands the prefix into a real path before the file is included. Using a prefix keeps the stored value short and independent of where Joomla is installed.

8.2 Why Functions, Not Classes

Both the condition and the action point to plain PHP functions, not class methods. The model includes the file once and calls the function by name. A condition function must return true or false. An action function performs its work and returns nothing. Keep these functions simple and self-contained.

Back to top

9. Creating Your Own Post-installation Messages

If you build extensions, you can add your own messages. The usual place is your extension's post-installation script, the script Joomla runs after your package is installed or updated. You call one method on the com_postinstall model and pass an array of options.

use Joomla\CMS\Factory;

$options = [
    'extension_id'       => $myExtensionId,
    'type'               => 'message',
    'title_key'          => 'COM_FOOBAR_POSTINSTALL_TITLE',
    'description_key'    => 'COM_FOOBAR_POSTINSTALL_DESCRIPTION',
    'language_extension' => 'com_foobar',
    'language_client_id' => 1,
    'version_introduced' => '2.0.0',
    'enabled'            => 1,
];

Factory::getApplication()
    ->bootComponent('com_postinstall')
    ->getMVCFactory()
    ->createModel('Messages', 'Administrator', ['ignore_request' => true])
    ->addPostInstallationMessage($options);

The example above is a plain message: the simplest type and the one most likely to just work. The link and action types need a few more keys, described below.

9.1 The Required Options

The method validates your input and throws a clear exception when something is missing. The rules are:

  • extension_id, type, title_key, description_key, and language_extension are always required.
  • type must be exactly message, link, or action.
  • For link and action, you also need an action_key and a condition_file plus condition_method.
  • For link, set action to the URL. For action, set action_file and action (the function name), and the file must exist on disk.

9.2 Finding the extension_id

Every message needs the numeric extension_id of the extension that owns it. You can read it from the #__extensions table. For a component:

SELECT extension_id, name, type, element, client_id
FROM #__extensions
WHERE element = 'com_foobar';

For a plugin you must also match the folder, because the same element name can exist in different plugin groups:

SELECT extension_id, name, type, element, folder, client_id
FROM #__extensions
WHERE type = 'plugin'
  AND folder = 'system'
  AND element = 'foobar';

Inside an install or update script you do not need raw SQL: Joomla already knows your own extension id, so read it from the installer adapter instead of hard-coding a number.

9.3 Adding Is Safe to Repeat

The method checks for an existing row with the same extension, type, and title key. If the definition is identical, it does nothing. If it changed, it removes the old row and inserts the new one. This means you can call it on every update without creating duplicates, which is exactly what a post-installation script needs.

Be careful with type = link when you register it through addPostInstallationMessage. In current Joomla 6 the method validates a link key, but that key is not part of the accepted option list and is stripped out before the check runs. The practical result is that a link definition can throw "needs an action (URL)" even when you supplied the URL in the action key as the documentation says.

Until this is resolved, the safe choices are: use message when you only need to inform, use action for a controlled internal task, and if you really need a link, test it on a clean install of the exact Joomla version you target and inspect MessagesModel::addPostInstallationMessage() first. A plain database row also works if you insert it yourself.

9.5 Security: action Messages Run PHP

An action message is powerful precisely because its button executes a PHP function from action_file. Treat that power with care.

  • Keep the action_file inside your own extension. Never point it at user-supplied or remote content.
  • Inside the function, check the user's permissions before doing anything that changes data.
  • Make the action idempotent, so clicking the button twice does no harm.
  • Use the condition function only to return true or false. Never let it migrate data, write files, or change settings; conditions run often, including when Joomla counts messages.
  • Log important changes and fail gracefully, rather than trusting request input.

9.6 How This Differs From enqueueMessage()

Joomla has a second, more familiar way to show a message: Factory::getApplication()->enqueueMessage('Saved successfully.'). It looks similar but solves a different problem. Post-installation messages are durable; enqueued messages are not.

FeatureenqueueMessage()com_postinstall
Stored in the database No Yes
Survives a page reload No Yes
Can be dismissed permanently No Yes
Can include condition logic No Yes
Best for Immediate, one-time feedback Durable upgrade guidance

Use enqueueMessage() for "your changes were saved" feedback during a single request. Use com_postinstall for guidance that must wait on the dashboard until the administrator acts on it.

Back to top

10. Permissions and the Options Screen

com_postinstall uses Joomla's standard Access Control List (ACL). It defines a small set of actions.

ActionLets the user
core.manage Open the component and read the messages.
core.edit.state See and use the Hide, Archive, and Read Again buttons.
core.admin Open the Options screen and edit permissions.

So a user can be allowed to read messages without being allowed to change their state. The Options button in the toolbar appears only for users with core.admin, and the Options screen itself contains just the Permissions tab. There are almost no settings to tune here, which fits a component whose whole job is to relay messages from elsewhere.

Back to top

11. Web Services API

Many Joomla core components ship a REST API under /api/index.php/v1/... so external tools can read or change data. com_postinstall is a deliberate exception: it has no Web Services API. There is no API controller, no public route, and no token-based endpoint for post-installation messages.

The reason is practical. These messages are short-lived, administrator-only notices that often run PHP actions or evaluate live conditions. Exposing them to remote clients would add risk without adding real value. If you need to read or clear them programmatically, you do it inside Joomla, through the same model method that the component itself uses, for example from a CLI plugin:

use Joomla\CMS\Factory;

$model = Factory::getApplication()
    ->bootComponent('com_postinstall')
    ->getMVCFactory()
    ->createModel('Messages', 'Administrator', ['ignore_request' => true]);

$count = $model->getItemsCount();

This keeps the logic, the conditions, and the cache handling consistent with the screen you see in the administrator.

Back to top

12. SEO and Metadata

com_postinstall is a backend-only component, so it has no direct effect on SEO. It produces no frontend pages, no URLs that search engines can reach, and no metadata. Search engines never see a post-installation message.

The indirect effect, though, is real and worth saying. Many post-installation messages exist precisely to protect or improve your site: a new security header, a changed default that affects how content renders, a setting that influences performance. Acting on these messages keeps your site healthy, and a healthy, secure, fast site is the foundation of good SEO. So the rule is simple: read the messages, do what they ask when it makes sense, and your public site benefits even though the component itself stays invisible.

Back to top

13. Common Mistakes and Pitfalls

13.1 Treating Messages as Spam

Symptom: You click "Hide All" without reading, every time.

Fix: Post-installation messages are rare and usually important. Read each one before hiding it. Many describe a security or behaviour change you genuinely need to know about.

13.2 Thinking Hidden Means Deleted

Symptom: You hid a message and now you cannot find it again.

Fix: Hidden messages are not deleted, only set to enabled = 0. Use the Reset Messages button on the empty-state screen to bring them all back, or Read Again for an archived one.

13.3 Looking at the Wrong Extension

Symptom: A message you expected is not in the list.

Fix: The screen filters by extension. By default it shows the Joomla core. Use the Showing messages for dropdown to switch to the extension that left the message.

13.4 Developer: Missing Condition File

Symptom: addPostInstallationMessage throws an exception during install.

Fix: For link and action types, the condition_file (and, for actions, the action_file) must exist on disk at the moment you register the message. Check your RAD path prefix (admin:// or site://) and that the file ships in your package.

13.5 Developer: Wrong Language Settings

Symptom: The card shows raw keys like COM_FOOBAR_POSTINSTALL_TITLE instead of text.

Fix: Set language_extension to the extension that owns the keys and language_client_id to the right side (1 for backend, 0 for frontend), and make sure the language file is installed.

Symptom: Registering a type = link message with addPostInstallationMessage throws "needs an action (URL)", even though you set the URL.

Fix: This is a known validation quirk in current Joomla 6, where the method checks a link key that it has already stripped from the options. Use message or action instead, or insert the row directly, and test link messages on the exact Joomla version you target. See section 9.4.

Back to top

14. Best Practices

If you remember only a few things from this article, remember these:

  • Check System → Manage → Post-installation Messages after every Joomla or extension update.
  • Read each message before you hide it. They are infrequent and usually matter.
  • Use Archive for messages you want to keep for later, and Hide for those you are truly done with.
  • Remember that nothing is deleted: Reset Messages and Read Again bring messages back.
  • As a developer, register messages from your post-installation script so they survive updates without duplicating.
  • Use conditions so a message appears only while it is relevant, and disappears once the user acts.
  • Always use language keys, never hard-coded text, so your messages stay translatable.
Back to top

15. Quick Reference

SCREEN
  System > Manage > Post-installation Messages
  URL: index.php?option=com_postinstall

MESSAGE TYPES
  message   informative only, no button
  link      button opens a URL
  action    button runs a PHP function

STATES (enabled column)
  1   published   shown as active card
  2   archived    shown with "Read Again"
  0   hidden      stored but not shown

BUTTONS
  Hide this message   enabled -> 0
  Archive             enabled -> 2
  Read Again          enabled -> 1 (from archived)
  Hide All Messages   all of one extension -> 0
  Reset Messages      all of one extension -> 1

DATABASE
  #__postinstall_messages   one row per message

RAD PATH PREFIXES
  site://    -> site root (JPATH_ROOT)
  admin://   -> administrator (JPATH_ADMINISTRATOR)

DEVELOPER API
  bootComponent('com_postinstall')
    ->getMVCFactory()
    ->createModel('Messages', 'Administrator', ['ignore_request' => true])
    ->addPostInstallationMessage($options);

PERMISSIONS
  core.manage       open and read
  core.edit.state   hide / archive / republish
  core.admin        Options screen

WEB SERVICES API
  none (no REST endpoint)
Back to top

16. Summary

com_postinstall is a small but useful piece of Joomla. Here is what to keep in mind:

  • It shows post-installation and upgrade messages from Joomla and its extensions, in the administrator only.
  • Messages come in three types: a plain notice, a link, or a PHP action.
  • The enabled column gives each message a state: published, archived, or hidden. Nothing is ever deleted.
  • All messages live in #__postinstall_messages and store language keys and RAD paths, not final text.
  • The model loads, conditions, caches, and translates the messages before the template renders them as cards.
  • Developers register messages from a post-installation script with addPostInstallationMessage, safely and repeatably.
  • There is no Web Services API; the component is meant for the people who run the site.

Most of the time you only glance at this screen, hide a message, and move on. But when a post-installation message appears after an update, it is often the clearest warning you will get that something on your site needs attention. If your Joomla site has a stack of unread messages, or you are not sure whether a past update left a setting half-changed, it pays to have someone read them with you and check the underlying configuration. That is exactly the kind of quiet, careful Joomla maintenance work I enjoy.

Back to top
Postinstall messages in Joomla
Peter Martin
Peter Martin

Joomla specialist and Linux admin for fast, secure and scalable websites.