Poezio is a terminal-based XMPP client which aims to replicate the
feeling of terminal-based IRC clients such as irssi or weechat; to
this end, poezio originally only supported multi-user chats and anonymous
authentication.
This new release has mostly internal improvements, but a few improvements and
fixes as well.
Thanks to all contributors and users!
Features
Implementation of Message Retraction (XEP-0424) as the sending side.
Various improvements to the react plugin, notably a way to convert :emoji:
aliases to real emojis.
Overhaul of the hide_exit_join option (more in the next section).
Updates to hide_exit_join
The hide_exit_join option is meant to avoid displaying all join/part presences
since the MUC (XEP-0045) behaviour is heavily presence-based for now.
It is an integer, which can be -1 (display all exit/joins), 0 (display none),
and a positive value n (display anything inactive for more than n seconds).
How this worked previously is that poezio did not even add join/exit messages if
they matched the criteria, making its a bit difficult if you both did not want
to clutter your screen with mostly irrelevant information, while at the same time
being able to view them – e.g. if you are moderating the room –.
Now the positive value’s quirky behavior stays the same, but in the case of
-1 or 0, the join/exit messages will be kept in the buffer at all times,
but not displayed when the value is 0. This option can be set at runtime,
and the effects are instantaneous.
Since this is a special kind of value and not a boolean, /toggle will not
work on it, therefore two new "aliased keys" have been added for users who want
to bind keypresses to this toggling:
_toggle_presences_local to show or hide presences in the current MUC.
_toggle_presences_global to show or hide presences globally.
Fixes
The API used internally for message retraction or moderation is no longer
limited to the last 100 messagess.
Fixed the config file handling on Guix or related distributions where the config
file could actually be a symlink (in which case it produced undesired behavior).
Custom plugin and theme load should keep working on python 3.15, which removes
a number of deprecated APIs in python’s importlib.
The /xhtml command had been broken for a while.
Some coroutines in the admin or irc plugin were not awaited, which
broke functionality and produced unwanted errors in the output.
Fixed a traceback when receiving reactions from an unopened conversation.
Fixed a display bug in semi-anonymous rooms showing the room jid
(room@server/nick) for users when joining/leaving, which is useless.
Fixed a case where self-ping would be disabled when the room disconnects us,
instead of trying to rejoin later.
Packaging
Link Mauve updated both the flatpak and the sticker-picker plugin.
Goran updated the guix package.
Docs
Missing plugins documentation has been added.
Internal
As hinted in my previous post, a large effort was made towards better
typing and linting. This means there were a huge number of changes:
Which is risky, but at the same time since most of those changes added
stricter type checking, there are few possible regressions (and a few were
caught already, thanks to the kind people running the main branch).
The XMPP Standards Foundation (XSF) is excited to announce the 29th XMPP Summit, the first XMPP Summit to take place fully online!
The XMPP Summit will be held from Friday 4th September to Saturday 5th September 2026, both days between 13:00 - 16:00 UTC.
The XSF invites everyone interested in development of XMPP technologies to attend, and discuss all things XMPP remotely!
The online XMPP Summit
The XMPP Summit is where the XMPP community comes together to discuss protocol development (such as XMPP extensions (XEPs)), implementation experience, and the future of the ecosystem.
As this is the first online XMPP Summit, it’s intentionally kept lightweight.
The goal is not to replicate the in-person XMPP Summit experience, but to provide value that complements our existing asynchronous communication channels.
Favored topics will likely be follow-ups to topics discussed during Summit 28, advance current work on extensions (XEPs), discuss implementation pain points, and improvement of collaboration between projects.
In general, the intention is to make it easier for more XMPP community members to participate, too.
Cost: Free (registration and topic proposals appreciated)
Who participates at the Summit?
Similar to an unconference at the beginning all interested participants can suggest topics and others can indicate via votes whether or not they are interested in these topics.
Afterwards a rough order of topics is established that will be followed in moderation with the participants.
How does the Summit work?
If you have ever followed a thread on the Standards Mailing List or taken part in a discussion on the public XSF channel you should be familiar with this.
The different topics are broken up by short breaks that are great for networking and getting to know other XMPP developers.
Agreeing on a common strategy or even establishing a rough priority for certain features in our decentralized and interoperable technology and protocol can be challenging.
To get the most out of the Summit, you should have a background in reading (and maybe even writing) XEPs.
If you are simply an enthusiastic user or admin, we regularly have booths at various conferences (e.g. FOSDEM, CLT, FrOSCon) that are a great opportunity to meet with us, too.
Either way, everyone is welcome to participate!
If we’ve caught your attention, we will then hopefully see you at the XMPP Summit 29. Read on!
Participation
If you’re interested in attending, please help us by filling out your details on the XMPP wiki page for Summit 29.
To edit the page, reach out to an XSF member to enter and update your details or you’ll need a wiki account, which we’ll happily provide for you.
To obtain an account on the XMPP wiki, please contact the Sysops who will be glad to create it for you (to avoid the spaming).
Contact us using the communication channels listed below.
If your plans change, please remove your name from the list.
Please also consider listing your agenda proposals and if you want to have a short talk: Topic proposals
Please be respectful of others’ time, perspectives, and personal circumstances.
Online participation can be demanding; we encourage everyone to help keep discussions constructive and focused.
Communication
To ensure you receive all relevant information, updates and announcements about the event, make sure that you’re signed up to the Summit mailing list and joined the Summit chatroom (Webview).
Spread the word! Feel free to use our communication channels (see page footer).
We are really excited to already see people signing up.
Looking forward to meeting all of you online this time!
As we’re preparing the upcoming Openfire 5.1.0 release, I’ve been spending a lot of time looking at parts of the codebase that have been around for a long time.
Some of them date back to assumptions that were perfectly reasonable when Java 5 was current, IPv6 was still considered “future tech”, Docker didn’t exist yet, and “cloud-native” wasn’t a phrase anyone but meteorologists used.
Yet somehow, Openfire deployments that started in those days are still running today.
That got me wondering:
What’s the oldest Openfire deployment that you still run?
Not necessarily the oldest version (although I’d love to hear that too), but the oldest continuously running installation, the oldest surviving user database, or perhaps the weirdest setup that somehow still works despite years of upgrades, migrations and changing infrastructure.
I suspect there are Openfire instances out there that have survived datacenter migrations, moved from physical hardware to virtual machines to containers, switched databases more than once, and outlived several generations of administrators. Some probably still contain configuration decisions that nobody fully understands anymore. Is anyone still running Wildfire? Jive Messenger?
Honestly, I love those stories from the trenches. The odd workarounds, the “temporary” fixes that became permanent infrastructure, the upgrade that everyone expected to fail but somehow didn’t, or the deployment that quietly kept running for a decade without anyone thinking much about it.
One of the things I appreciate most about infrastructure software is that success often becomes invisible. If a messaging server quietly keeps working for ten years, nobody talks about it. But that kind of stability is actually a huge achievement (both for the software and for the people operating it). I think that’s something we, as a community, can be genuinely proud of.
For Openfire 5.1.0, we’ve been modernizing quite a few internals:
support for Java 25
upgrades to Netty 4.2 and various database drivers
improvements around reverse proxies and DNS handling
clustering improvements
security hardening
performance fixes for larger deployments.
While doing that work, we constantly try to balance modernization with compatibility for long-running installations. That balancing act becomes much easier when we understand how people actually deploy and operate Openfire in the real world, which, apart from simply wanting to hear your stories, is another reason for me to ask this question.
So: I’d love to hear your stories! How old is your deployment? What version did you start with? What infrastructure changes has it survived over the years? Are there plugins or integrations you absolutely depend on? What operational lessons have you learned?
And perhaps most importantly: what surprised you most about running Openfire long-term?
I’m hoping this thread becomes a collection of deployment stories, operational lessons, and perhaps a bit of Openfire history.
Looking forward to hearing your stories!
We’d love to hear from you! Please join our community forum or group chat and let us know what you think!
For other release announcements and news follow us on Mastodon or X
The Ignite Realtime community is pleased to announce a new release of Openfire, version 5.0.5. The full changelog has more details with the highlights being bug fixes and bundled library updates whilst we continue to work on an upcoming 5.1.0 feature release.
You can obtain the new version of Openfire for your platform from its download page. The sha256sum values for the release artifacts are:
Just like any other product or project by the XSF, the Newsletter is the result of the voluntary work of its members and contributors. If you are happy with the services and software you may be using, please consider saying thanks or help these projects!
Being an elected member of the XMPP Standards Foundation signals a commitment to open standards and professional engagement in / with the XMPP community. Here, your membership helps position the XSF as a healthy organization, which in itself is valuable. It also grants voting rights on technical and administrative matters within the XSF. The application is a light-weight and free of cost process and you can use your membership to get more involved more easily, too. If you are interested in joining the XMPP Standards Foundation as a member, please apply to our 2nd quarterly call for members admissions before May 17th, 2026, 00:00 UTC.
XMPP Events
XMPP Sprint in Berlin (DE / EN): will take place in June, from Friday 19th to Sunday 21st 2026, at the Wikimedia Deutschland e.V. offices in Berlin, Germany. If this sounds like the right event for you, come and join us! Just make sure to list yourself here, so we know how many people will attend and we can plan accordingly. If you have any questions or concerns, join us at the chatroom: sprints@muc.xmpp.org!
XMPP at FOSSY 2026: This year’s edition of FOSSY, the fourth Free and Open Source Software Yearly conference, will take place during the month of August, from Thursday 6th to Sunday 9th 2026 at the University of British Columbia, Vancouver, Canada. As always, there will be an XMPP Track. The call for proposals remains open until May 22, 2026. Once again, this year JMP is pleased to announce its annual offer for funding to the potential speakers who would like to host a talk on the XMPP track. Please, join them at discuss@conference.soprani.ca, and don’t hesitate to ask for more information!
OpenPGP refresh for Conversations: This project aims to modernize PGP encryption within Conversations, a Jabber/XMPP client, by integrating cryptographic operations and adopting updated messaging standards. Furthermore, the project will implement and update the modern OpenPGP standards for XMPP (XEP-0373 and XEP-0374) by making use of Stanza Content Encryption (SCE). This transition not only benefits users who prefer PGP-based encryption but also serves as a critical building block for the development of OMEMOv2.
Matridge spaces: Matridge is a gateway for XMPP users to transparently chat in Matrix rooms. It is an XMPP server-side component that acts as a Matrix client and makes it possible to pilot a Matrix client from any XMPP client. It implements modern instant messaging features such as rich replies, spaces, attachments, emoji reactions and threads. It is self-hosting friendly, community-lead, written in python and based on slidge, an XMPP gateway library.
Libervia progress note 2026-W16: a complete and comprehensive blog post about the Audio/Video implementation, email gateway, work on installation/configuration simplification and the new forge, focus on web frontend and redesign and work done with current metadata reduction and serverless XMPP (Tor, contacts e2ee, new pubsub implementation) by Goffi.
aTalk has released versions 5.2.2 and 5.3.0 of its encrypted instant messaging with video call and GPS features for Android. Both versions bring a lot of ‘under the hood’ changes. Please refer to the release notes or check out the intermediate changelog from 5.2.1 to 5.3.0 for all the details.
Fluux Messenger, has released versions 0.15.0, 0.15.1 and 0.15.2, of its modern, cross-platform XMPP client for communities and organizations. These versions introduce a large list of additions and new features like 12 built-in themes, reaction-based polls for MUC rooms with deadlines, full-text message search across all conversations and rooms, font size adjustment buttons, activity log events are clickable and allow you to navigate to the relevant conversation and message, and the ability to disable push notifications just to name a few of them! The list also expands to improvements, bugfixes and it’s way longer than what we can mention in here! Please, go straight to the fulll changelog for all the details, because there are a lot of them!
Fluux Messenger Rose Pine theme.
Gajim has released version 2.4.6 of its free and fully featured chat app for XMPP. This release can now give you a clue if it’s night for your contacts and comes with improvements for the activity feed, better display of mentions, fixed message scrolling, and many bugfixes. Thank you for all your contributions! You can take a look at the changelog for all the details.
Gajim: A message mentioning you
Monal has released version 6.4.20 for iOS and macOS with a rather large list of fixes.
Monocles has released version 2.1.5 of its chat client for Android. This release brings fixes on import settings and hide offline. It implements swipe to previous or next media in preview, clear push notification configuration values, and work on UnifiedPush to add support for link activity among other niceties!
Movim has released version 0.33, code named Halley! After months of work and hundreds of commits, this is the biggest Movim release ever made. This release massively scales up Movim’s architecture while introducing long-awaited, and exclusive, new features like spaces, shortcuts, hats, swipe to reply, videoconference, audio and screen sharing, categorizing content during calls, refactored notifications, new administration tools and accessibility improvements, a big Funding Campaign for 2026, and even two new mascots: Miho and Stash! A lot of work was also done to improve accessibility thanks to NLnet funding. Head over the official release announcement and dive directly into the exciting things you can find in this release!
Movim: Spaces; already compatible with ejabberd. Prosody support coming very soon!
Poezio has released versions 0.16.1 and 0.17 of its console XMPP client. The former is a bugfix release that brings mostly fixes and internal stuff, but also adds the ability to see redacted/moderated messages if you wish so, particularly useful if you are the one moderating. The latter is a small release focused on receiving and sending message reactions! You can find all the details in their respective links.
Poezio: receiving message reactions
Poezio: sending message reactions
Profanity has released version 0.18.0 of its console based XMPP client written in C. This release adds spellcheck highlighting support and implements asynchronous external editor support while introducing quite a few bugfixes. Please make sure to read the changelog for all the details!
XMPP Servers
ProcessOne has released ejabberd 26.04. This security release includes options to limit XML parser, and other minor bugfixes. It is strongly encouraged that you update ejabberd as soon as possible. Make sure to read the changelog for all the details and a complete list of fixes and improvements on this release.
Prosody IM is pleased to announce versions 13.0.5 and 0.12.6. These are security releases for the Prosody 13.0.x stable series and for the old Prosody 0.12.x old stable series respectively. They fix multiple security issues, some memory leaks, some smaller bugs and changes which have been implemented since the previous releases. Full details about the security vulnerabilities can be found in the security advisory. All Prosody operators on 13.0.4 or earlier, or on 0.12.5 or earlier, are encouraged to upgrade to 13.0.5 and/or 0.12.6 as soon as possible, or to review the advisory and implement appropriate mitigations. Read changelog for all the details, and as always, detailed download and install instructions are available on the download page for your convenience. Note: Support for the 0.12.x series ends in June 2026. This means it will no longer receive any fixes or updates, even for security issues. It is likely that 0.12.6 will be the last release from this series. Check out the guide on upgrading Prosody and the release notes for 13.0.0 before you upgrade to the 13.0.x series.
librssguard-xmpp, a plugin for the RSS Guard desktop feed reader that offers basic XMPP support to fetch real-time (push) ATOM/PubSub entries and single/multi user chat messages.
python-nbxmpp, a Python library that provides a way for Python applications to use the XMPP network, version 7.2.0 has been released. Full details on the changelog.
QXmpp, the cross-platform C++ XMPP client and server library, versions 1.14.6, 1.14.7, 1.15.0 and 1.15.1 have been released. Full details on the changelog.
Slidge versions 0.3.8 and 0.3.9 have been released. The former comes with the usual bug fixes and introduces image link previews and contact- and room-specific commands along with a lot of internal changes to improve the code maintainability. The latter is a bugfix release, notably for a crash triggered by using chat commands introduced by a refactor of the commands system in the previous release. You can check the intermediate changelog from 0.3.7 to 0.3.9 for all the details.
Extensions and specifications
The XMPP Standards Foundation develops extensions to XMPP in its XEP series in addition to XMPP RFCs. Developers and other standards experts from around the world collaborate on these extensions, developing new specifications for emerging practices, and refining existing ways of doing things. Proposed by anybody, the particularly successful ones end up as Final or Active - depending on their type - while others are carefully archived as Deferred. This life cycle is described in XEP-0001, which contains the formal and canonical definitions for the types, states, and processes. Read more about the standards process. Communication around Standards and Extensions happens in the Standards Mailing List (online archive).
Proposed
The XEP development process starts by writing up an idea and submitting it to the XMPP Editor. Within two weeks, the Council decides whether to accept this proposal as an Experimental XEP.
This document specifies an enhanced Multi-User Chat protocol that is broadly backwards compatible with that of XEP-0045(Multi-User Chat), but adds a number of key improvements.
This specification defines an XMPP protocol extension that enables services to require payment before granting access to a resource. It provides a payment-system neutral invoice format supporting multiple concurrent payment options, including bank transfers (SEPA, IBAN, UPI) and instant-settlement networks (Lightning Network), and integrates with the existing CAPTCHA challenge mechanism defined in XEP-0158 (CAPTCHA Forms).
Accepted as Experimental by council vote on 2026-03-31 (dg)
Deferred
If an experimental XEP is not updated for more than twelve months, it will be moved off Experimental to Deferred. If there is another update, it will put the XEP back onto Experimental.
Version 0.2.0 of XEP-0509 (Initial Authentication Pipelining)
Updates based on implementation. (dwd)
Last Call
Last calls are issued once everyone seems satisfied with the current XEP status. After the Council decides whether the XEP seems ready, the XMPP Editor issues a Last Call for comments. The feedback gathered during the Last Call can help improve the XEP before returning it to the Council for advancement to Stable.
Looking for job offers or want to hire a professional consultant for your XMPP project? Visit our XMPP job board.
Newsletter Contributors & Translations
This is a community effort, and we would like to thank translators for their contributions. Volunteers and more languages are welcome! Translations of the XMPP Newsletter will be released here (with some delay):
Contributors:
To this issue: emus, cal0pteryx, Gonzalo Raúl Nemmi, Ludovic Bocquet, XSF iTeam
This XMPP Newsletter is produced collaboratively by the XMPP community. Each month’s newsletter issue is drafted in this simple pad. At the end of each month, the pad’s content is merged into the XSF GitHub repository. We are always happy to welcome contributors. Do not hesitate to join the discussion in our XSF Communications Team group chat (MUC) and thereby help us sustain this as a community effort. You have a project and want to spread the news? Please consider sharing your news or events here, and promote it to a large audience.
Tasks we do on a regular basis:
gathering news in the XMPP universe
short summaries of news and events
summary of the monthly communication on extensions (XEPs)
review of the newsletter draft
preparation of media images
translations
communication via media accounts
Unsubscribe from the XMPP Newsletter
For this newsletter either log in here and unsubscribe or simply send an email to newsletter-leave@xmpp.org.
(If you have not previously logged in, you may need to set up an account with the appropriate email address.)
In XEP-0424, the message sent for the retraction is now returned after being sent.
Fixes
The XEP-0045 plugin will now raise exceptions if the wrong parameters are provided (e.g. specifying a "pfrom" when not running as a component).
Passing the iterator parameter to get_items() in XEP-0030 was broken.
Build
The rust build is now optional, which means platforms that are not supported by codeberg CI (like windows or mac OS) can install the package from pypi without setting up a rust toolchain, at the cost of some performance. Packagers should beware that the jid module is properly built.
Links
You can find the new release on codeberg, pypi, or the distributions that package it in a short while.
We are pleased to announce a new minor release from our stable branch.
This is a security release for the Prosody 0.12.x old stable series. It
addresses multiple security issues, some memory leaks and some smaller bugs
which have been fixed since the previous release.
Full details about the security vulnerabilities can be found in our security
advisory. We encourage all
Prosody operators on 0.12.5 or earlier to upgrade to 0.12.6 or 13.0.5 as soon
as possible, or to review the advisory and implement appropriate mitigations.
Note: Support for the 0.12.x series ends in June 2026. This means it will
no longer receive any fixes or updates, even for security issues. It is likely
that 0.12.6 will be the last release from this series. Check our guide on
upgrading Prosody and the release notes
for 13.0.0 before you upgrade to the 13.0.x series.
We are pleased to announce a new minor release from our stable branch.
This is a security release for the Prosody 13.0.x stable series. It fixes
multiple security issues, some memory leaks and some smaller bugs and changes
which have been implemented since the previous release.
Full details about the security vulnerabilities can be found in our security
advisory. We encourage all
Prosody operators on 13.0.4 or earlier to upgrade to 13.0.5 as soon as
possible, or to review the advisory and implement appropriate mitigations.
This is a maintenance release with a few notable additions: RTL language support, faster reconnection after stream-management resume, and a handful of reliability fixes scattered across reconnect edge cases.
RTL layout support (Arabic and Hebrew) and User interface tweaks
Fluux Messenger now renders correctly in right-to-left languages. Arabic and Hebrew translations are included in this release. Both are beta quality, so if you spot translation errors or layout glitches, please open an issue. Getting community feedback early is the fastest way to improve coverage.
On the UI side, blockquotes now use decorative quotation marks, a small polish detail that also helps in RTL contexts where quote direction matters.
Reconnection: faster and far more reliable
A significant chunk of this release is dedicated to making reconnects work the way they should. If you&aposve seen Fluux Messenger freeze after waking your laptop, or loop on reconnect attempts, most of those scenarios are addressed here.
Faster resume: When stream management successfully resumes a session, the client now skips redundant MAM queries. If the stream was cleanly resumed, there&aposs no need to re-fetch history, so reconnection feels almost instant in good network conditions.
Sleep/wake handling: Two separate bugs could cause the app to stall after a system sleep. One was a Tauri-specific reconnect stall, now recovered via native keepalive with a proxy fallback. The other was a post-wake auto-connect stall that happened after SASL negotiation completed but before the session was fully established. Both are fixed.
Loop prevention:
The reconnect attempt counter was incorrectly capped at the backoff ceiling, meaning it would stop growing and could trigger premature reconnect loops. That&aposs fixed, and superseded connection attempts now get a dedicated error class so they&aposre handled cleanly rather than causing UI freezes.
MUC room state: Room state is now properly preserved across stream-management resume and interrupted fresh sessions. Previously, a reconnect could wipe stored room messages or fail to restore saved rooms, leaving history empty after resume. Both are fixed: live room messages are written directly to IndexedDB, and rooms are restored through the connect call so history loads correctly after SM resume.
SASL2 and FAST token improvements
Several fixes land around SASL2 and FAST token handling:
The websocket stream from attribute is now correctly set, which is required for SASL2 to be accepted on compliant servers.
FAST token rotation now works correctly across page-reload reconnects.
Token authentication is retried when the server field was initially empty on login.
A spurious "FAST token deleted" log message that appeared on first login (when no token existed yet) is suppressed.
The SASL2 user-agent identifier is updated, and server-side FAST token invalidation is triggered on logout.
The outbound stream-management state is now hydrated on resume, preventing an ackQueue crash that could occur in certain reconnect scenarios.
Performance: per-conversation subscriptions
Typing indicators and draft state now use per-conversation subscriptions rather than a single global subscription. This reduces re-renders in the conversation list during background sync, which was noticeable when many conversations were active simultaneously. The list stays responsive while the client is catching up on missed messages.
Other fixes worth noting
Notifications: On web, notifications now use ServiceWorker.showNotification() for reliable delivery, replacing the previous approach that could silently fail.
Image lightbox: The lightbox no longer upscales images past their natural resolution, displaying the full-resolution original at actual size.
Web image cache: If the cache fetch fails, the client now falls back to loading directly from the URL instead of showing nothing.
Upload errors: HTTP upload errors are now displayed in the UI rather than failing silently. HTTP upload URLs are also now allowed.
Dynamic import failures: On failure, the client probes the runtime before reloading, and auto-reloads if the probe succeeds, skipping unnecessary hard reloads.
Discovery calls: Service discovery calls now run before the serial session-setup chain, which can shave time off the initial connection in some server configurations.
Accessibility: The scroll-to-bottom FAB now uses inert instead of aria-hidden, and the message toolbar "more" menu button vertical alignment is fixed.
If you run into issues, especially around the new RTL translations or any of the reconnect scenarios, please open an issue. This release fixes a lot of edge cases and we want to make sure nothing slipped through.
Here is yet another poezio release focused on message reactions!
Poezio is a terminal-based XMPP client which aims to replicate the
feeling of terminal-based IRC clients such as irssi or weechat; to
this end, poezio originally only supported multi-user chats and anonymous
authentication.
Message Reactions
This is a small release as it only contains this feature, both receiving
and sending.
Receiving
Receiving reactions is enabled by default and can be turned off
(requires a restart) using the enable_reactions option.
The reactions received on a message are shown under the message contents,
prefixed with a colored pipe to differenciate between reactions and normal
text. The pipe color can be configured in the theme through COLOR_REACTIONS_TEXT,
by default it is the same color as information messages in the UI.
When there is only one of a specific emoji, it is displayed without a count,
but starting from two, the emoji is suffixed with [n] where n is the number
of times the emoji has been used to react to the message.
Sending
Sending reactions is achieved through a new react plugin and its /react
command.
/react works by providing a full timestamp as the first argument, and then
as many emojis as you want (starting from 0 to remove reactions), separated by
spaces. Non-emoji characters are rejected.
The command is made usable through the completion system; if completing the first
argument, it will iterate backwards through the most recent messages. If completing
the second, it will iterate through the emoji reactions already received for
that message – if any –.
This release adds new options that limit max memory used by XML parser used to process XMPP payloads, to prevent potential Denial of Service attack. The default values for pre-auth provide sufficient protection for ejabberd against non-authenticated users on c2s and s2s, so there is no need to change your configuration.
The option max_stanza_elements sets a limit on the maximum number of XML elements that an individual stanza can contain. By default, this option is set to infinity.
The pair of options pre_auth_max_stanza_elements and pre_auth_max_stanza_size define separate limits for sessions that haven&apost authenticated yet. The session will switch to the limits defined by the options max_stanza_elements and max_stanza_size after the client has successfully authenticated. The default values for these options are: 32 for pre_auth_max_stanza_elements and 8192 for pre_auth_max_stanza_size.
All those options are recognized inside listener sections, and can be applied to ejabberd_c2s and ejabberd_s2s_in listeners.
ChangeLog
Core
Add new listener options to limit xml parser accepted input
Improve leave_cluster command to work even in own node
New predefined keyword DATABASE_PATH that points to the Mnesia spool dir
Support HOST keyword in sql_database toplevel option, set nice default value
Provide more details in log messages when using SQLite
Update documentation of jwt_key to match the Docs site
ejabberd_config: New default_ram_db/3 clause that checks module support
ejabberd_sm: Remove session_counter, used for get_vh_session_number now removed
Modules
mod_http_fileserver: Use integer in ejabberd_hooks:add as expected by "make hooks"
mod_invites: Add --enable-bootstrap=no to configure options to bypass download (#4558)
mod_invites: don&apost crash in get_invite_by_invitee_t for sql backend (#4566)
mod_invites: quick howto for creating integrity check checksums
mod_invites: remove dependency on jquery
mod_mqtt: Define RAM callbacks as optional
mod_mqtt: Use default_ram_db only if it really supports RAM storage
mod_roster: Fix bug introduced in 26.03 in commit d5c1440 (#4564)
mod_roster_sql: Cast approved integer as boolean when exporting Mnesia to SQL
mod_shared_roster_sql: Fix typo introduced 10 years ago in commit 0ea0ba30
In recent years, software security has become a hot topic due to regulatory pressure (NIS2, EU Cyber Resilience Act, etc.). Beyond regulations, software communities and open source maintainers have also put security into focus, because open source libraries are often part of commercial software supply chains. This has reached the Erlang/Elixir ecosystem as well, and that is a good thing.
In this post, the SAFE team takes us through SAFE, Erlang Solutions’ security analysis tool for the BEAM, covering what it does, how it works, and what makes it effective in practice.
The BEAM is secure by default (Up to a point)
The BEAM’s architecture eliminates entire classes of bugs for free. Isolated process memory means processes can’t manipulate each other’s state, they only communicate through messages. Immutable data structures rule out a whole category of aliasing bugs. These are real wins, and they come without any effort from the developer.
But “secure by default” only goes so far. Application-level vulnerabilities, e.g., XSS, SQL injection, CSRF, unsafe deserialization, atom exhaustion, are just as possible in Erlang and Elixir as anywhere else. That’s the gap SAFE exists to cover.
What is SAFE?
SAFE (Security Analysis for Erlang/Elixir) is Erlang Solutions’ static analysis tool for the BEAM. It analyses compiled BEAM files rather than source code, so it works consistently across Erlang, Elixir, and Phoenix, including mixed-language codebases. SAFE is free for open source projects (subject to approval) and commercially available for other use cases.
SAFE detects a broad range of vulnerabilities, including:
Cross-Site Scripting (XSS)
SQL injection
Command injection
Remote Code Execution
Denial of Service (e.g. atom exhaustion)
Unsafe serialisation
Cross-Site Request Forgery (CSRF)
Session hijacking, fixation, and information leakage
Content Security Policy (CSP) misconfigurations
Data-flow analysis: the core of what makes SAFE different
The central feature that sets SAFE apart is data-flow analysis. Most static analysis tools work by pattern matching, they look for known dangerous function calls and flag them. The problem is that not every call to a dangerous function is actually dangerous. Without understanding the possible values flowing through the code, a tool has no way to tell the difference, and the result is a high rate of false positives.
SAFE takes a different approach. Data-flow analysis tracks what values variables can hold at each point in the program. This information is then used to filter the initial list of vulnerability candidates, eliminating findings where the data can be proven safe, and surfacing only the ones that represent real risk.
The practical impact of this is significant. In our tests across 7 popular open source BEAM projects (~70,000 lines of code), SAFE produced a false positive rate of 7.78% and that number continues to improve as we refine our analysis. We also manually review findings during development to further sharpen the filtering.
How data-flow analysis eliminates false positives
Example 1 — guarded atom creation
A common pattern in Elixir is to convert a binary to an atom only after validating it against an allowlist:
def safe_to_atom(binary, allowed) do
if Enum.member?(allowed, binary), do: String.to_atom(binary)
end
A pattern-matching tool sees String.to_atom/1 and flags it. SAFE’s data-flow analysis traces the possible values of binary at the point of the call and determines that it is always a member of a finite, controlled list so it eliminates the finding entirely.
Example 2 — finite compile-time atom generation
Metaprogramming is common in Elixir. Consider this pattern where atoms are generated at compile time:
@variants [:case_a, :case_b, :case_c]
#
# ...
#
for var <- @variants do
defp unquote(var)() do
env = Application.get_env(:my_app, :environment)
if env == "test" do
unquote(Macro.escape(Module.get_attribute(__MODULE__, :"test_#{var}")))
else
unquote(Macro.escape(Module.get_attribute(__MODULE__, var)))
end
end
end
The number of atoms created here is strictly bounded by the length of @variants, a compile-time constant. SAFE calculates this and correctly determines the atom count is finite hence no vulnerability. A tool without data-flow analysis cannot make this determination.
What SAFE catches in practice
Session management vulnerabilities
Session management vulnerabilities allow attackers to gain unauthorised access to user sessions, which can lead to data theft, unauthorised actions, and account takeover. SAFE detects session hijacking, session fixation, and session information leakage. Session hijacking occurs when an attacker gains access to cookie contents. To prevent this, thehttp_only and secure attributes should both be set to true when setting a cookie. Below is a vulnerable example:
@spec set_cookie(Plug.Conn.t()) :: Plug.Conn.t()
def set_cookie(conn) do
Plug.Conn.put_resp_cookie(conn, "my_cookie", "true",
http_only: false,
max_age: @max_age # an integer
)
end
Session fixation is an attack where a malicious user plants a session ID for a victim to use, then hijacks their account after login. The Plug.Session API provides the configure_session/2 function for renewing the session ID. When this function is misconfigured by setting the renew option to false, session fixation can occur.
Session information leakage can be prevented by encrypting cookie contents. Encryption can be enabled by setting the encryption_salt in Plug.Session. For non-session cookies, encryption can be enabled via the encrypt option in Plug.Conn.put_resp_cookie/4.
Content Security Policy misconfigurations
When it comes to Content Security Policy (CSP), any policy is better than none. Using :put_secure_browser_headers without a custom policy won’t be enough on its own:
There are also dedicated plugs for this, such as PlugContentSecurityPolicy:
plug PlugContentSecurityPolicy,
SAFE inspects the policy content itself and will flag an overly permissive default. You should define your own policy, keeping it as restrictive as possible to avoid unintentionally whitelisting too much. Beyond that, SAFE checks that all pipelines accepting HTML have CSP protection at all, a gap that is easy to miss during development.
Results from the field
The top three vulnerability types are XSS, DoS, and CSP. Notably, a large share of DoS findings trace back to unguarded String.to_atom/1 calls, a known footgun that is consistently flagged in Erlang/Elixir documentation, yet still appears frequently in practice.
SAFE found a total of 90 vulnerabilities, of which 7 were false positives after manual investigation, a false positive ratio of 7.78%, and an area of active improvement.
The projects tested are anonymized to avoid identification, since the disclosed vulnerabilities may still be present in production systems. While this limits full reproducibility, responsible disclosure takes priority. Contact us at safe@erlang-solutions.com to discuss the methodology in detail.
Closing notes
Security analysis on the BEAM is a genuinely hard problem. The same flexibility that makes Erlang and Elixir so expressive also makes it easy to introduce subtle vulnerabilities without realising it. SAFE is built specifically for this environment, grounded in academic research, and designed to give you signals you can act on rather than noise you have to filter.
If you maintain an open-source project, SAFE is free: reach out to us at safe@erlang-solutions.com and after a short approval process you’ll receive a licence at no cost. For commercial use or a third-party security review of your system, get in touch with the team.
While working on Borogove there has been a desire to have full-text search of locally-stored chat message history. For web-based apps the main storage engine in use is IndexedDB, which is a rather low-level system and certainly doesn’t have easy facilities for this kind of operation. So what’s the simplest, performant way to implement a full-text search on IndexedDB?
In case you are wondering “what is full-text search?” for our purposes we are going to be looking at a search where we want to find any message that contains all the words the user has typed, in any order
Table Scan
While this won’t be our final solution, it is almost always the right place to start. If your data is small (say, under 10k documents) then a table scan is pretty quick, and definitely the simplest option
// Helper so we can use promises with IndexedDB
function promisifyRequest(request) {
return new Promise((resolve, reject) => {
request.oncomplete = request.onsuccess = () => resolve(request.result);
request.onabort = request.onerror = () => reject(request.error);
});
}
const stopwords = ["and", "if", "but"];
function tokenize(s) {
return s.toLowerCase().split(/\s*\b/)
.filter(w => w.length > 1 && w.match(/\w/) && !stopwords.includes(w));
}
function stemmer(s) {
// Optional, https://www.npmjs.com/package/porter2 or similar
}
async function search(q) {
const qTerms = new Set(tokenize(q).map(stemmer));
const tx = db.transaction(["messages"], "readonly");
const store = tx.objectStore("messages");
const cursor = store.openCursor();
const result = [];
while (true) {
const cresult = await promisifyRequest(cursor);
if (!cresult?.value) break;
if (new Set(tokenize(cresult.value.text).map(stemmer)).isSupersetOf(qTerms) {
result.push(cresult.value);
}
cresult.continue();
}
return result;
}
Even though we aren’t doing anything fancy with the database yet, there are still a lot of important building blocks here
First we tokenize the query. This means to chunk it up into “words”. Words don’t have to be exactly real words, they can be consistent parts of words or anything else, so long as you tokenize your query and document text in the same way. Here we use a simple strategy where we trust the \b word-break regex pattern, strip any extra whitespace, ignore any empty words or words made of only non-word characters (again, as determined by \w, nothing fancy), and also ignore any stopwords. A “stopword” is a very common word that is not useful to include in the search query such as “and”. Mostly, stopwords are useful to avoid blowing up the index size later, but we include it here for now for consistency
Next we stem the tokens. This is optional and depends on the kind of search you’re trying to build. The purpose of a stemmer is to make searches for eg “flying” also match messages containing the word “fly”
Then we iterate over all the items in the object store. If you wanted the results in a particular order, you could instead iterate over an index on the store in a particular order. We tokenize and stem the text from each item and check if it contains all the “words” from qTerms, if so it is part of the results.
Use an Index
Now what if you have many messages (one million or more, perhaps) and the simple table scan is just too slow. How can we speed this up? With IndexedDB we only get one kind of index: an ordered index, usually build on a B-Tree. This is not exactly what many full-text indexes are built on, but still we can get a very big performance boost without too much more complexity.
First in the onupgradeneeded migrator we need to create the index:
This is a “multiEntry” index which means that the index will get one entry for each item in the array stored at this key, rather than indexing on the array as a whole piece. So when we store a new message we need to include the terms as an array:
Now, this does not let us search by our full query, but rather only by one word. How does this help us? Well, we can iterate over only documents which match at least one of the terms in our query. Which one should we pick? Counting items is pretty fast, so let’s pick whichever one has the smallest number of results:
async function search(q) {
const qTerms = new Set(tokenize(q).map(stemmer));
const tx = db.transaction(["messages"], "readonly");
const store = tx.objectStore("messages");
const index = store.index("terms");
// Figure out which search term matches the fewest messages
let probeTerm = null;
let probeScore = null;
for (const term of qTerms) {
const score = await promisifyRequest(index.count(IDBKeyRange.only(term)));
if (!probeTerm || score < probeScore) {
probeTerm = term;
probeScore = score;
}
}
// Using the smallest list of messages that match one term
// Find the ones that match every term
const result = [];
const cursor = index.openCursor(IDBKeyRange.only(probeTerm));
while (true) {
const cresult = await promisifyRequest(cursor);
if (!cresult?.value) break;
if (new Set(cresult.value.terms).isSupersetOf(qTerms)) {
result.push(cresult.value);
}
cresult.continue();
}
// Sort results
return result.sort((a, b) => a.timestamp < b.timestamp ? -1 : (a.timestamp > b.timestamp ? 1 : 0));
}
The operation to count the index for each term is pretty fast, but if you found this prohibitive, you could also store these counts in their own keys and update them as you insert new messages. Once we know which is the smallest, we then do the same scan as before, but only over that much smaller subset. The tokenized and stemmed terms are stored so we can compare against those directly here rather than doing it again.
Now if we want it sorted we have to do it ourselves, just like a DB engine would with this kind of query where the order we want does not match the index order.
On a test set of one million messages, this simple index was enough to take the performance from unusable grinding to almost instant responses, since the number of messages in the smallest term is usually still well under 10k.
Here is 0.16.1, a bugfix and cleanup release for poezio, with exactly one
new feature as an improvement over an existing plugin.
Poezio is a terminal-based XMPP client which aims to replicate the
feeling of terminal-based IRC clients such as irssi or weechat; to
this end, poezio originally only supported multi-user chats and anonymous
authentication.
Features
Handle redacted/moderated messages in /display_corrections as well
Fixes
A bug in occupant comparison introduced in 0.16, leading to inconsistent MUC state in some cases.
Several fixes to MAM syncing and history gaps in MUC, which should be more reliable (but not perfect yet).
Issues around MUC self-ping (XEP-0410) where you could not ever leave a room if it was enabled.
A bug in the new tcp-reconnect plugin which would traceback when disconnected.
Loading issues with plugins defined in entrypoints, of which the most common is poezio-omemo.
Internal
Introduction of a harsher linting pipeline.
Plenty of typing and linting fixes.
Added poezio-omemo to the plugins list in pyproject, for easier installation.
Real-time messaging sits at the centre of many modern digital products. From live chat and streaming reactions to betting platforms and collaborative tools, users expect communication to feel immediate and consistent.
When pressure builds, the system doesn’t typically collapse. It starts to drift. Messages arrive slightly late, ordering becomes inconsistent, and the platform feels less reliable. That drift is often the first signal that chat scalability is under strain.
Imagine a live sports final going into overtime. Millions of viewers react at once. Messages stack up, connections remain open, and activity intensifies. For a moment, everything appears stable. Then delivery slows. Reactions fall slightly out of sync. Some users refresh, unsure whether the delay is on their side or yours.
Those moments reveal whether the system was designed with fault tolerance in mind. If it was, the platform degrades predictably and recovers. If it wasn’t, small issues escalate quickly.
This article explores what breaks first in real-time messaging and how early architectural decisions determine whether users experience resilience or visible strain.
Real-Time Messaging in Live Products
Live products place real-time messaging under immediate scrutiny. On sports platforms, streaming services, online games, and live commerce sites, messaging is visible while it happens. When traffic spikes, performance issues are exposed immediately.
User expectations are already set. WhatsApp reports more than 2 billion monthly active users, shaping what instant communication feels like in practice. That expectation carries into every live experience, whether it is chat, reactions, or collaborative interaction.
Live environments concentrate demand rather than distribute it evenly. Traffic clusters around specific moments. Concurrency can double within minutes, and those users remain connected while message volume increases sharply. That concentration exposes limits in chat scalability far more quickly than steady growth ever would.
The operational impact tends to follow a familiar pattern:
Live scenario
System pressure
Business impact
Sports final
Sudden surge in concurrent users
Latency becomes public
Product launch
Burst of new sessions
Onboarding friction
Viral stream moment
Rapid fan-out across channels
Inconsistent experience
Regional spike
Localised traffic surge
Infrastructure imbalance
For live platforms, volatility comes with the territory.
When delivery slows or behaviour becomes inconsistent, engagement drops first. Retention follows. Users rarely blame infrastructure. They blame the platform.
Designing for unpredictable load requires architecture that assumes spikes are normal and isolates failure when it occurs. If you operate a live platform, that discipline determines whether users experience seamless interaction or visible strain.
High Concurrency and Chat Scalability
In live environments, real-time messaging operates under sustained concurrency rather than occasional bursts. Users remain connected, they interact continuously, and activity compounds when shared moments occur.
High concurrency is not simply about having many users online. It involves managing thousands, sometimes millions, of persistent connections sending and receiving messages at the same time. Every open connection consumes resources, and messages may need to be delivered to large groups of active participants without delay.
This is where chat scalability really gets tested.
In steady conditions, most systems appear stable. When demand synchronises, message fan-out increases rapidly, routing paths multiply, and coordination overhead grows. Small inefficiencies that were invisible during testing begin to surface. Response times drift. Ordering becomes inconsistent. Queues expand before alerts signal a problem.
High concurrency does not introduce entirely new issues. It reveals architectural assumptions that only become visible at scale. Concurrency increases are predictable in live systems. The risk lies in whether the messaging layer can sustain that pressure without affecting user experience.
Messaging Architecture Limits
The pressure created by high concurrency does not stay abstract for long. It shows up in the messaging architecture.
When performance degrades under load, the root cause usually sits there. At scale, every message must be routed, processed, and delivered to the correct subscribers. In distributed systems, that requires coordination across servers, and coordination carries cost. Under sustained traffic, small inefficiencies compound quickly.
Routing layers can become bottlenecks when messages must propagate across multiple nodes. Queues expand when incoming traffic outpaces processing capacity. Latency increases as backlogs grow. If state drifts between nodes, messages may arrive late or appear out of sequence.
This is where the earlier discussion of chat scalability becomes tangible. It is not only about supporting more users. It is about how efficiently the architecture distributes load and maintains consistency when concurrency remains elevated.
These limits rarely appear during controlled testing with predictable traffic. They emerge under real usage, where concurrency is sustained and message patterns are uneven.
Well-designed systems account for this from the outset. They reduce coordination overhead, isolate failure domains, and scale horizontally without introducing fragility. When they do not, performance drift becomes visible long before a full outage occurs, and users feel the impact immediately.
Fault Tolerance and Scaling
If you operate a live platform, this is where design choices become visible.
Once architectural limits are exposed, the question is how your system behaves as demand continues to rise.
Scaling real-time messaging is about making sure that when components falter, the impact is contained. Distributed systems are built on a simple assumption: things break. You will see restarts, reroutes and unstable network conditions. But the real test is whether your architecture absorbs the shock or amplifies it.
Systems built with fault isolation in mind tend to recover locally. Load shifts across nodes. Individual components stabilise without affecting the wider service. Systems built around central coordination points are more vulnerable to ripple effects.
In practical terms, the difference shows up as:
Localised disruption rather than cascading instability
Brief slowdown instead of prolonged degradation
Controlled recovery rather than platform-wide interruption
These behaviours define whether users experience resilience or instability.
Fault tolerance determines how the system behaves when conditions are at their most demanding.
Real-Time Messaging in Entertainment
Entertainment platforms expose weaknesses in real-time messaging quickly because traffic converges rather than building steadily over time.
When a live event captures attention, users respond together. Demand rises sharply within a short window, and those users remain connected while interaction increases. The stress on the system comes not from gradual growth, but from concentrated activity.
Take the widespread Cloudflare outage in November 2025. As a core infrastructure provider handling a significant share of global internet traffic, its disruption affected major platforms simultaneously. The issue was due to underlying infrastructure, but the impact was immediate and highly visible because so many users were active at once.
Live gaming environments operate under comparable traffic patterns by design. During competitive matches on FACEIT, large numbers of players remain connected while scores, rankings, and in-game events update continuously. Activity intensifies around key moments, increasing message throughput while persistent connections stay open.
Across these environments, the pattern is consistent. Users connect simultaneously, interact continuously, and expect immediate feedback. When performance begins to drift, the impact is shared rather than isolated.
A Note on Architecture
This is where architectural choices begin to matter.
Platforms that manage sustained concurrency and recover predictably under pressure tend to share certain structural characteristics. In messaging environments, MongooseIM is one example of infrastructure designed around those principles.
In practical terms, that means:
Supporting large numbers of persistent connections without central bottlenecks
Distributing load across nodes to reduce coordination overhead
Containing failure within defined boundaries rather than allowing it to cascade
Maintaining message consistency even when traffic intensifies
These design choices do not eliminate volatility. They determine how the system behaves when it does.
In live entertainment platforms, that distinction shapes whether pressure remains internal or becomes visible to users.
Conclusion
Real-time messaging raises expectations that are easy to meet under steady conditions and far harder to sustain when attention converges.
What breaks first is rarely availability. It is timing. It is the subtle drift in delivery and consistency that users notice before any dashboard signals a failure.
Live environments make that visible because traffic arrives together and interaction compounds quickly. Concurrency is not the exception. It is the operating model. Whether the experience holds depends on how the architecture distributes load and contains failure.
Designing for that reality early makes scaling more predictable and reduces the risk of visible strain later.If you are building or modernising a platform where real-time interaction matters, assess whether your messaging architecture is prepared for sustained concurrency. Get in touch to continue the conversation.
We have shipped Fluux Messenger 0.15, and it is packed with major advancements. After the excitement of the FOSDEM launch, the team put their heads down on three things users were asking for most: the ability to find past messages, a messenger that looks and feels different from Discord, and richer collaboration tools for group rooms.
Find anything, instantly
Full-text search is now built into Fluux Messenger, every conversation, every room, searchable, locally and instantly.
The search engine runs entirely on your device using an IndexedDB inverted index with prefix matching and highlighted result snippets. No messages leave your machine to power this. For rooms with deep history on the server, results are supplemented with MAM (Message Archive Management) server-side queries, giving you the best of both worlds: speed from local cache, completeness from the archive.
A find-in-page mode (Cmd+F) lets you scan within any conversation, mirroring the browser experience developers expect.
Make it yours: a full theme system
Fluux Messenger now ships with a proper design token system, three-tier (Foundation → Semantic → Component), and a theme picker bundled in the Appearance settings.
Twelve themes are available out of the box: Fluux, Dracula, Nord, Gruvbox, Catppuccin Mocha, Solarized, One Dark, Tokyo Night, Monokai, Rosé Pine, Kanagawa, and GitHub. If none of them are quite right, you can import your own theme or inject CSS snippets directly. A global accent color picker with theme-specific presets lets you go further without writing a single line of code.
Font size adjustment is now in Appearance settings as well.
Polls in group rooms
Reaction-based polls are now a first-class feature in MUC rooms. Create a poll with custom emojis, set a deadline, and let participants vote. The room enforces voting rules server-side, so results are trustworthy. Polls can be closed and reopened, and an "unanswered" banner nudges participants who haven&apost voted yet. Results are visualized inline and captured in the activity log.
Faster connections with FAST authentication
Fluux Messenger now supports XEP-0484: FAST (Fast Authentication Streamlining Tokens) alongside SASL2. Reconnection after a network interruption or wake from sleep is now possible in the web version.
Media cache
Downloaded images are now cached to the filesystem, so they load instantly on revisit and don&apost count against your bandwidth twice. A new storage management screen in settings lets you see and clear the cache.
Polish and fixes worth noting
Emoji picker (emoji-mart) with dynamic viewport positioning, so it never clips off-screen
Last Activity (XEP-0012) — offline contacts now show how long ago they were last seen
Syntax highlighting for code blocks, lazily loaded per language, with theme integration and a fullscreen modal for long snippets
IRC-style mention detection with consistent per-user colors (XEP-0392)
VCard popovers on occupant and member list nicks
Scroll-to-bottom button now shows an unread badge and implements two-step scroll: first click jumps to the new message marker, second click goes to the very bottom
Particle burst animation when adding a reaction, and a message send slide-up animation
Upgraded to React 19 with the React Compiler for automatic memoization, and Vite 8 with lazy-loaded views for a faster startup
A note on Windows signing
Starting with 0.15, the Windows binary is no longer signed. This is a temporary decision while we work through the signing infrastructure — full details are in issue #290. On install, Windows will prompt you to manually trust the application. We know this isn&apost ideal and are working to restore signed builds.
I have recently started experimenting with adding support for three additional databases in Openfire: MariaDB, Firebird and CockroachDB.
This work is still exploratory. Before committing to this direction, I would like to get a better understanding of whether this is actually valuable to the Openfire community.
I have prepared initial pull requests for each database:
These are not production-ready, but intended to validate feasibility and surface any obvious issues.
Why these databases?
MariaDB is widely used as a drop-in replacement for MySQL. Although Openfire supports MySQL, MariaDB is not explicitly treated as a first-class option. Given how often it is used in practice, formal support could provide more confidence for administrators.
Firebird represents a more niche but still relevant ecosystem. It is commonly found in long-lived, on-premise systems where changing the database is not realistic. Supporting it could make Openfire easier to adopt in those environments.
CockroachDB targets modern, distributed deployments. With its PostgreSQL compatibility and focus on resilience and scalability, it could make Openfire more attractive for cloud-native and multi-region setups.
Trade-offs
Supporting additional databases comes with a cost: more code paths, more testing, and more long-term maintenance. The key question is whether the added flexibility justifies that complexity.
Feedback wanted
Before taking this further, I would really appreciate feedback from the community:
Are you using (or considering) MariaDB, Firebird or CockroachDB with Openfire? Would official support influence your deployment decisions? Do you see this as valuable, or as unnecessary complexity?
Please share your thoughts on the pull requests or through the usual community channels!
For other release announcements and news follow us on Mastodon or X
Welcome to the XMPP Newsletter, great to have you here again!
This issue covers the month of March 2026.
The XMPP Newsletter is brought to you by the XSF Communication Team.
Just like any other product or project by the XSF, the Newsletter is the result of the voluntary work of its members and contributors. If you are happy with the services and software you may be using, please consider saying thanks or help these projects!
Being an elected member of the XMPP Standards Foundation signals a commitment to open standards and professional engagement in / with the XMPP community. Here, your membership helps position the XSF as a healthy organization, which in itself is valuable. It also grants voting rights on technical and administrative matters within the XSF. The application is a light-weight and free of cost process and you can use your membership to get more involved more easily, too. If you are interested in joining the XMPP Standards Foundation as a member, please apply to our 2nd quarterly call for members admissions before May 17th, 2026, 00:00 UTC.
XMPP Events
XMPP Sprint in Berlin (DE / EN): will take place in June, from Friday 19th to Sunday 21st 2026, at the Wikimedia Deutschland e.V. offices in Berlin, Germany. If this sounds like the right event for you, come and join us! Just make sure to list yourself here, so we know how many people will attend and we can plan accordingly. If you have any questions or concerns, join us at the chatroom: sprints@muc.xmpp.org!
XMPP at FOSSY 2026: This year’s edition of FOSSY, the fourth Free and Open Source Software Yearly conference, will take place during the month of August, from Thursday 6th to Sunday 9th 2026 at the University of British Columbia, Vancouver, Canada. As always, there will be an XMPP Track and the call for proposals is open until May 22, 2026.
Once again, this year JMP is pleased to announce its annual offer for funding to the potential speakers who would like to host a talk on the XMPP track. Please, join them at discuss@conference.soprani.ca, and don’t hesitate to ask for more information!
JoinJabber: thanks to the excellent work done by one of the community members, the whole site is now fully available in Portuguese (BR)! You can check the translation status on their web translation status page and help out with other translations!
Introducing CLabber: A terminal UI (TUI) XMPP (Jabber) client written in Common Lisp.
Upgrade ejabberd on Debian NOW: Chances might be that you are running a Debian based ejabberd server. Unfortunately push for all your Monal users on that server will break in less than 2 months. And chances are that some of your S2S connections are already failing today. By Thilo Molitor for the monal-im blog.
XMPP Software News
XMPP Clients and Applications
aTalk has released versions 5.2.0 and 5.2.1 of its encrypted instant messaging with video call and GPS features for Android. The former version implements XEP-0384 (OMEMO Encryption), decryption of OMEMO messages, upgrades smack to support XEP-0420 (Stanza Content Encryption) and other relevant updates and fixes, while the latter introduces a fix for an incorrect fetching. You can check the intermediate changelog from 5.1.0 to 5.2.0 and 5.2.0 to 5.2.1 for all the details.
Conversations has released versions 2.19.13, 2.19.14 and 2.9.15 for Android. These releases bring fixes for a crash when changing OMEMO bundle access model, a crash when sharing Quicksy XMPP addresses and a fix for Quicksy registration on older devices, shows hats in public conferences where available, shows a warning in the chat if a contact is in different time zone and it is night time for them, a refactored automatic DND handling (based on system DND), and a warning in the chat window if contact is in DND mode. You can take a look at the changelog for all the details or check the intermediate changelogs from 2.19.12 to 2.19.13, 2.19.13 to 2.19.14 and/or 2.19.14 to 2.19.15.
Conversations showing contact’s local time in the chat window
Cheogram has released version 2.19.0-5 for Android. A bugfix release that addresses many crash fixes, never use iterative DNS for DNSSEC, fallback public server is now jabber.fr, merge security fixes from upstream, allow emoji search by emoji (eg for reactions), better isApp logic to default to commands list or not, and fix for channel avatars on some older servers. Make sure to check out the changelog for all the details.
Fluux Messenger has released versions 0.13.3 and 0.14.0, of its modern, cross-platform XMPP client for communities and organizations, with a list of additions, new features, improvements and bugfixes that is way longer than what we could ever mention in here! You can go straight to the full changelog or check the intermediate changelogs from 0.13.2 to 0.13.3 and/or 0.13.3 to 0.14.0 for all the details!
Fluux Messenger team chat
Gajim has released version 2.4.5 of its free and fully featured chat app for XMPP. This release lets you know when somebody reacted to one of your messages. It also comes with automatic timezone updates and improvements for macOS, and bugfixes. Thank you for all your contributions! You can take a look at the changelog for all the details.
Gajim automatic timezone updates
Monal has released version 6.4.19 for iOS and macOS with a rather large list of fixes.
Monocles has released version 2.1.4 of its chat client for Android. This release brings fixes for message moderation, truncated text, link click handling, disappearing reactions popup, MUC destruction, a crash when message body not spannable, allow camera/mic in command UI webview and pick channel binding fallback when server has no XEP-0440 (SASL Channel-Binding Type Capability) support.
Poezio has released version 0.16 of its console XMPP client. This release implements XEP-0425 (Moderated Message Retraction) a receiving side of moderation, XEP-0424 (Message Retraction) retraction events, XEP-0377 (Blocking Command Reports) a new /report plugin to report spam, a new /tcp-reconnect to kill TCP connections on faulty networks, a tls_verify_cert option that can be set to false if the user wishes so, and several fixes. You can find all the details in the release announcement.
Moderated message retraction testing in Poezio
Profanity has released version 0.17.0 of its console based XMPP client written in C. The release announcement for this version is so long that it spans over 200 lines worth of information, which is a lot more than what we could ever list in here, so please make sure to read the changelog for all the details!
Wimsy has released version 0.0.5 of it cross-platform XMPP client built with Flutter.
xmpp-web has released version 0.12.0 of its lightweight web chat client for XMPP server. You can read the intermediate changelog from 0.11.0 to 0.12.0 for all the details.
XMPP Servers
The Ignite Realtime community is happy to announce the release of Openfire 5.0.4. This release continues the efforts to provide a stable 5.0.x series releases whilst they finalize work on the upcoming 5.1.0 release. Please refer to the full changelog for all the details or to the intermediate changelog for versions 0.5.3 to 0.5.4.
MongooseIM has released MongooseIM 6.6.0 with more additions, changes and fixes than what we can reasonably list in here! Make sure to read the changelog for all the details!
ProcessOne is pleased to announce another bugfix release: ejabberd 26.03. This brings support for roster pre-approval, and more than 100 commits with bugfixes all around, many of them dedicated to the new mod_invites, including also many security fixes. Make sure to read the changelog for all the details and a complete list of fixes and improvements on this release.
XMPP Libraries & Tools
matridge, the Matrix to XMPP gateway based on Slidge and nio, versions 0.3.3 has been released. You can read the intermediate changelog from 0.3.2 to 0.3.3 for all the details.
QXmpp, the cross-platform C++ XMPP client and server library, versions 1.14.4 and 1.14.5 have been released. Full details on the changelog.
Rusty-Filer, an external XMPP file server for HTTP uploads. An alternative to the internal HTTP file servers of Ejabberd and Prosody, written in Rust, version 1.0.0 has been released.
Siltamesh, a simple bridge between Meshtastic and XMPP networks, version 0.2.0 has been released.
Slixmpp, the MIT licensed XMPP library for Python 3.7+ version 1.14.1 has been released. You can read the official release announcement for all the details.
Xepher, a plugin written in C++23 that adds full XMPP support to WeeChat. It targets XEP-0459 (XMPP Compliance Suite 2022) and implements a broad set of modern XEPs — including XEP-0384 (OMEMO encryption), XEP-0313 (Message Archive Management), XEP-0363 (HTTP file upload), XEP-0472 (Pubsub Social Feed) microblogging via PubSub, and more.
Extensions and specifications
The XMPP Standards Foundation develops extensions to XMPP in its XEP series in addition to XMPP RFCs. Developers and other standards experts from around the world collaborate on these extensions, developing new specifications for emerging practices, and refining existing ways of doing things. Proposed by anybody, the particularly successful ones end up as Final or Active - depending on their type - while others are carefully archived as Deferred. This life cycle is described in XEP-0001, which contains the formal and canonical definitions for the types, states, and processes. Read more about the standards process. Communication around Standards and Extensions happens in the Standards Mailing List (online archive).
Proposed
The XEP development process starts by writing up an idea and submitting it to the XMPP Editor. Within two weeks, the Council decides whether to accept this proposal as an Experimental XEP.
This specification defines a way to explicitly mention a person or groups of people.
New
No new XEPs this month.
Deferred
If an experimental XEP is not updated for more than twelve months, it will be moved off Experimental to Deferred. If there is another update, it will put the XEP back onto Experimental.
Added security consideration. Added alt text to example. (spw)
Last Call
Last calls are issued once everyone seems satisfied with the current XEP status. After the Council decides whether the XEP seems ready, the XMPP Editor issues a Last Call for comments. The feedback gathered during the Last Call can help improve the XEP before returning it to the Council for advancement to Stable.
Looking for job offers or want to hire a professional consultant for your XMPP project? Visit our XMPP job board.
Newsletter Contributors & Translations
This is a community effort, and we would like to thank translators for their contributions. Volunteers and more languages are welcome! Translations of the XMPP Newsletter will be released here (with some delay):
Contributors:
To this issue: emus, cal0pteryx, Gonzalo Raúl Nemmi, Ludovic Bocquet, Sairam Bisoyi, XSF iTeam
This XMPP Newsletter is produced collaboratively by the XMPP community. Each month’s newsletter issue is drafted in this simple pad. At the end of each month, the pad’s content is merged into the XSF GitHub repository. We are always happy to welcome contributors. Do not hesitate to join the discussion in our Comm-Team group chat (MUC) and thereby help us sustain this as a community effort. You have a project and want to spread the news? Please consider sharing your news or events here, and promote it to a large audience.
Tasks we do on a regular basis:
gathering news in the XMPP universe
short summaries of news and events
summary of the monthly communication on extensions (XEPs)
review of the newsletter draft
preparation of media images
translations
communication via media accounts
Unsubscribe from the XMPP Newsletter
For this newsletter either log in here and unsubscribe or simply send an email to newsletter-leave@xmpp.org.
(If you have not previously logged in, you may need to set up an account with the appropriate email address.)
Chances might be that you are running a Debian based ejabberd server.
Unfortunately push for all your Monal users on that server will break in less than 2 month.
And chances are that some of your S2S connections are already failing today.
Some background
The Web-PKI is moving away from certificates having bot, the TLS Web Server Authentication and the TLS Web Client Authentication extended key usage enabled.
Most CAs already stopped issuing certificates with the TLS Web Client Authentication EKU set or will stop doing so in a few month.
Traditionally both servers of an S2S connections in XMPP authenticate to each other.
One is the server part of a TLS handshake (and needs the server EKU), the other one is the client part of the TLS handshake (and needs the client EKU).
Which one is which, solely depends upon which server starts the underlying TCP connection (that one becomes the client in this connection).
The underlying problem
This mutual authentication breaks, once the client part can’t present a certificate having the client EKU.
All TLS libraries fail the authentification in this case.
The solution
Fortunately almost all TLS libraries allow users to customize the certificate validation process and ejabberd was updated in version 25.08 (August 2025)
to do exactly this: ignore the EKU when validating the certificate.
But unfortunately it was too late to go into Debian Trixie, the current stable Debian version.
Debian
This is where the real problem starts. Many server operators use Debian because it is so extremely stable and well maintained.
Of course Debian provides point releases to upgrade packages if they have some severe bug
(like not being able to properly participate in S2S connections).
The next point release will contain a fix for the problem, but that will still take more than a month to reach servers.
How to fix the situation
I urge all ejabberd server operators to take one of the following steps as soon as possible:
Add trixie-proposed-updates to your sources.list file and update ejabberd to version 24.12-3+deb13u2
Install the official packages by ProcessOne from here: https://repo.process-one.net/ (caution: these packages use /opt/ejabberd, so you’ll need to copy your config from /etc/ejabberd over!)
Switch to Prosody (Prosody’s fix for the S2S client EKU problem made it into Debian Trixie)
Switch to some other distribution
If you absolutely don’t want to take any action, please enable at least dialback by adding mod_s2s_dialback: {} to the modules section of your ejabberd config. But be aware: while this will fix the S2S connection to Monal’s push servers, other servers might not have turned it on (both parts must turn it on to be effective). The security of the connection will also be degraded when using dialback rather than properly verifying certificates.
Last words
Many thanks to Holger Weiß and Philipp Huebner for fixing this bug in Debian!
Platform lock-in is often discussed as a commercial issue. Organisations adopt infrastructure that works well initially and later realise that moving away from those services becomes expensive or operationally disruptive.
For platforms that run continuously under heavy demand, the consequences appear somewhere else first. They appear in architecture.
Infrastructure choices influence how systems scale, how faults are contained, and how easily the platform can evolve as requirements change. In regulated environments those decisions often remain in place for years, which means architectural flexibility matters as much as technical capability.
When infrastructure becomes tightly coupled to a particular provider, systems may still perform well day to day. The real impact usually surfaces later when workloads grow, regulations change, or operational expectations increase. At that point platform lock-in risks begin to affect reliability as well as flexibility.
Why Platform Lock-in Matters in Regulated Environments
These architectural constraints become particularly visible in regulated industries where infrastructure decisions cannot be changed casually.
Financial services platforms must maintain traceable transactions and strict audit trails. Betting platforms process large volumes of activity during live sporting events. Streaming platforms deliver real-time content to global audiences who expect uninterrupted interaction.
Systems supporting these environments often remain active for long periods, which means infrastructure decisions made early in the system’s lifecycle can shape how the platform changes years later.
The Operational Impact of Vendor Lock-in
Many organisations already recognise the risks associated with vendor lock-in. The 2024 Flexera State of the Cloud Report found that 89% of organisations now operate multi-cloud strategies, with reducing infrastructure dependency and avoiding vendor concentration cited as key motivations.
The concern goes beyond procurement strategy. When platforms rely heavily on provider-specific services for messaging, orchestration, or event processing, those dependencies begin shaping how the system behaves under load.
In regulated environments that dependency can become a reliability concern. Infrastructure decisions that once simplified development may later restrict how systems scale, evolve, or respond to operational change.
Distributed Systems Architecture and Long-Running Platforms
The reason platform lock-in becomes particularly serious in regulated environments is tied to how many of these platforms operate: as long-running distributed systems.
Large-scale entertainment services rarely behave like short-lived workloads that restart frequently. Messaging layers, real-time interaction systems, and event pipelines maintain persistent connections while processing continuous streams of activity.
Why Long-Running Systems Behave Differently
Gaming platforms illustrate this clearly. Competitive environments host thousands of players interacting simultaneously, all of whom expect consistent state across the system. Betting platforms experience similar behaviour during major sporting events when users react instantly to changing odds. Streaming platforms see comparable spikes as audiences interact during live broadcasts.
These platforms rely on distributed systems architecture that must coordinate large numbers of connections and events while remaining continuously available.
Research published by ACM Queue examining large-scale distributed systems highlights how persistent connections and real-time workloads increase coordination pressure across system components, particularly during sudden spikes in concurrency.
When coordination layers rely heavily on platform-specific services, architectural dependency gradually builds. Over time the system begins to inherit those infrastructure constraints.
Reliability Requirements in High Reliability Systems
Systems operating under these conditions often prioritise stability over rapid iteration. Platforms designed as high reliability systems must remain available while managing constant traffic, evolving workloads, and unpredictable user behaviour.
Infrastructure decisions therefore have long-term consequences. When coordination, messaging, or state management rely on proprietary platform services, architectural flexibility narrows over time.
Why Gaming, Betting and Streaming Platforms Reveal Infrastructure Limits
Systems built as long-running distributed environments face their toughest tests during moments of concentrated demand. Entertainment platforms provide a clear example.
Large audiences often react simultaneously. A football match entering extra time can trigger thousands of betting transactions within seconds. A major esports tournament can bring large numbers of players online at once. Streaming platforms experience bursts of interaction as viewers respond together during live broadcasts.
Traffic Spikes and Scalable Distributed Systems
Systems supporting these environments must function as scalable distributed systems capable of handling sudden increases in activity without losing consistency or responsiveness.
Instead of steady growth, activity often arrives in waves. Large numbers of users connect, interact, and generate events within very short timeframes. The system must coordinate these interactions across multiple nodes while maintaining reliable communication between services.
Infrastructure that appears sufficient under normal conditions can struggle during these spikes if the surrounding architecture relies too heavily on provider-specific services.
Real-World Example: BET Software
These architectural pressures are particularly visible in betting platforms where activity surges during live sporting events.
BET Software operates large-scale betting technology platforms where thousands of users interact with markets simultaneously. During major sporting events systems must process rapid updates, recalculate market information, and distribute new data to users in real time.
Their distributed systems illustrate how reliability and responsiveness become essential in environments where activity concentrates around shared moments.
Architectures designed with flexibility across infrastructure layers tend to scale and recover more predictably than those tightly coupled to provider-specific services.
Architectural Patterns to Avoid Vendor Lock-in
Recognising the risks of vendor lock-in is useful only if it leads to better architectural decisions. Systems that remain adaptable across infrastructure layers often share several structural characteristics.
Decoupling Infrastructure Dependencies
Architectures designed to avoid vendor lock-in typically separate application logic from infrastructure services wherever possible. This allows teams to evolve system components independently without redesigning the entire system,
Designing Fault Tolerant Systems
Platforms that must operate continuously also benefit from architectures designed as fault tolerant systems, where failures can be contained locally rather than cascading across the entire platform.
Common patterns include:
Decoupled services that scale independently
Communication through open protocols rather than proprietary messaging layers
Distributed state management instead of provider-specific coordination services
Horizontal scaling across nodes
Infrastructure abstraction layers separating application logic from provider-specific implementations
These approaches help ensure that infrastructure choices support the system rather than define its limitations.
These patterns help ensure that infrastructure choices support the system rather than define its limitations.
Where Elixir Supports High Reliability Systems
Technology choices also influence how easily distributed systems can maintain reliability while remaining adaptable.
Languages built on the Erlang virtual machine, including Elixir, were designed for environments where systems must remain available while handling large numbers of concurrent processes. The runtime emphasises process isolation and supervision structures that allow failures to be contained locally rather than cascading across the system.
Building Fault Tolerant Systems for Long-Running Platforms
These characteristics make the platform particularly well suited for high reliability systems that must remain active while managing heavy concurrency.
The advantage lies in the runtime model rather than any single infrastructure provider. Systems built around resilient distributed behaviour are easier to evolve because they remain stable even as infrastructure decisions change around them.
Designing Systems That Reduce Platform Lock-in
Looking across these examples reveals a consistent pattern.
Platform lock-in becomes most visible in systems that must operate continuously while adapting to changing demand. Regulated environments amplify the challenge because infrastructure decisions often remain in place for years while platforms continue to evolve.
Gaming, betting, and streaming services make these limits easier to see. Sudden spikes in activity quickly expose architectural weaknesses, and systems designed with flexible infrastructure tend to scale and recover more predictably.
If you are building platforms where reliability and long-running distributed workloads matter, it may be worth assessing how your architecture handles platform lock-in. To explore these challenges further, get in touch with the Erlang Solutions team.
If you are upgrading from a previous version, there is a change in the SQL schemas, please read below. There are no changes in configuration, API commands or hooks.
This release adds a new column to the rosterusers table in the SQL database schemas to support roster pre-approval. This task is performed automatically by ejabberd by default.
However, if your configuration file has disabled update_sql_schema toplevel option, you must perform the SQL schema update manually yourself. Those instructions are valid for MySQL, PostgreSQL and SQLite, both default and new schemas:
ALTER TABLE rosterusers ADD COLUMN approved boolean NOT NULL DEFAULT false;
ALTER TABLE rosterusers ALTER COLUMN approved DROP DEFAULT;
You can ignore the second query on SQLite.
SASL channel binding changes
This version adds the ability to configure the handling of the client flag &aposwanted to use channel-bindings but was not offered one&apos. By default, ejabberd aborts connections that present this flag, as this could indicate the presence of a rogue MITM proxy between the server and the client that strips the exchanged data of information required for this.
This can cause problems for servers that use a proxy server which terminates the TLS connection (i.e. there is a MITM proxy, but it is approved by the server administrator). To handle this situation, we have added code to ignore this flag if the server administrator disables channel binding handling by disabling the -PLUS authentication mechanisms in the configuration file:
We also ignore this flag for SASL2 connections if offered authentication methods filtered by available user passwords did disable all -PLUS mechanisms.
ChangeLog
Core
Fix MySQL authentication for TLS connections that required auth plugin switch
Improve handling of scram &aposwanted to use channel-bindings but was not offered one&apos flag
Add ability for mod_options values to depend on other options
Don&apost fail to classify stand-alone chat states
Fix some warnings compiling with Erlang/OTP 29 (#4527)
ejabberd_ctl: Document how to set empty lists in ejabberdctl and WebAdmin
ejabberd_http: Add handling of Etag and If-Modified-Since headers to files served by mod_http_upload
ejabberd_http: Ignore whitespaces at end of host header
SQL: Add ability to mark that column can be null in e_sql_schema
Tests: Add tests for SASL2
Tests: Make table cleanup in test more robust
Modules
mod_fast_auth: Offered methods are based on available channel bindings
mod_http_api: Always hide password in log entries
mod_mam: Call store_mam_message hook for messages that user_mucsub_from_muc_archive was filtering out
mod_mam_sql: Only provide the new XEP-0431 fulltext field, not old custom withtext
mod_muc_room: Fix duplicate stanza-id in muc mam responses generated from local history (#4544)
mod_muc_room: Fix hook name in commit 7732984 (#4526)
mod_pubsub_serverinfo: Don&apost use gen_server:call for resolving pubsub host
mod_roster: Add support for roster pre-approval (#4512)
mod_roster: Fix display of groups in WebAdmin when it&aposs a list
mod_roster: in WebAdmin page, first execute SET actions, later GET
mod_roster_mnesia: Improve transformation code
mod_invites
Makefile: Run invites-deps only when files are missing
Fix path to bootstrap files
Check at start time the syntax of landing_page option (#4525)
Almost exactly one year since the last release, here is poezio 0.16.
Poezio is a terminal-based XMPP client which aims to replicate the
feeling of terminal-based IRC clients such as irssi or weechat; to
this end, poezio originally only supported multi-user chats and anonymous
authentication.
Features
Receiving side of moderation (XEP-0425) and retraction (XEP-0424) events
New /tcp-reconnect to kill TCP connections on faulty networks (#3406).
Due to the CA store usage default on 0.15, the historical TOFU way of managing
certs in poezio was broken. There is now a tls_verify_cert option that can
be set to false if the user wishes so.
The roster is now kept until the XMPP session ends (which means on a disconnect
with smacks (XEP-0198) enabled, the roster is kept until the session timeouts) (#3614)
Traceback in /affiliations due to slixmpp’s rust JID rewrite
Traceback in the /bookmarks tab
Infinite syncing of MAM history due to bad paging
Saving remote MUC bookmarks no longer force the JID as bookmark name
pkg_resources is no longer used.
Plenty of deprecationwarnings have been removed.
/set option=value would handle the = wrong and display the wrong thing.
Internal
Plenty of typing updates and fixes
Removals
Removal of uv as a first-party target for launch/update.sh (no vcware).
Intro In this edition of our Meet the Team series, we’d like to introduce Viktoria, Project Manager at Erlang Solutions.
She shares what it’s like to work across complex, multilingual projects, reflects on the highlights of her role so far, and gives a glimpse into the experiences that have shaped her journey.
What does your role as Project Manager at Erlang Solutions involve, and what have been some highlights so far?
Working as a Project Manager at Erlang Solutions is never dull. I had the opportunity to join a fascinating project focused on developing an intelligent virtual assistant for MUSE, the Italian science museum. My role spans multiple responsibilities, combining project management, Scrum Master duties, and product management.
Beyond building something innovative, we also faced the added complexity of a language barrier. Optimising a chatbot for accuracy required us to rethink how retrieval and validation function when the primary knowledge base is not in English, but in highly specialised Italian scientific language curated by museum experts.
In close collaboration with EbitMax and MUSE, we ensured that the system accurately reflects a carefully curated and continuously evolving knowledge base, while supporting interactions in Italian, German, and English.
What do you enjoy most about working at Erlang Solutions?
What I enjoy most is working closely with my team—exchanging ideas, solving problems, and learning together. I feel fortunate to collaborate across all business units, where everyone contributes to improving Tourio, our product. I also appreciate the opportunity to create new processes, continuously learn, and grow while tackling new challenges.
Most importantly, I value the flexibility of remote work. I used to travel extensively as a digital nomad; now I’m more settled, but living in a place with limited job opportunities makes this role even more meaningful to me.
Outside of work, how do you like to spend your time?
Outside of work, whenever the wind picks up, you’ll find me kitesurfing with my friends and my boyfriend. Before joining Erlang Solutions, I worked as a kite instructor, and I still occasionally teach on weekends.
When it’s not windy, I stay active with calisthenics or spinning at the gym. Sundays are usually spent cheering on my boyfriend at his local football matches. I also travel frequently to Hungary to spend time with my family and my dog—or to any destination where I can get back on the water.
Final thoughts
A big thank you to Viktoria for sharing her story with us. From leading collaborative projects to embracing new challenges, her approach reflects the curiosity and drive that shape our work at Erlang Solutions.
Stay tuned for more Meet the Team stories, where we continue to spotlight the people behind the technology.
Fluux Messenger 0.14.0 is a major release. Fluux Messenger is growing fast. Thank you to everyone contributing, testing, and spreading the word!
This release finally brings room management. Moderators can retract messages, owners can manage rooms end-to-end, contacts have real profiles now, and the fix list is longer than usual. A lot landed in this release.
What&aposs New
Full MUC Room Management
Fluux Messenger now supports the complete room lifecycle directly from the client. You can create, configure, and destroy MUC rooms without reaching for an admin console. Room owners also get full user management tools: change affiliations and roles, kick or ban occupants, and browse room directories with proper RSM pagination. A new modal lets you join any room directly by entering its JID.
This makes Fluux Messenger a serious option for teams self-hosting their own ejabberd server and managing communities day-to-day.
Message Moderation (XEP-0425)
Moderators can now retract messages posted by other users in MUC rooms, with full attribution and reason display. This is a meaningful step toward responsible community management inside open, sovereign messaging infrastructure — no proprietary platform required.
MUC Hat Management (XEP-0317)
Room owners can now define, assign, and remove hats for occupants via ad-hoc commands. Hats are a lightweight, expressive way to convey roles and status in a room beyond the standard affiliation model. The full hat management UI is accessible directly from the room interface.
Rich Contact Profiles with vCard (XEP-0054)
Contact information just got a lot more useful. Fluux Messenger now displays vCard data — full name, organisation, email, and country — in contact popovers and profile views. You can also edit your own vCard directly from profile settings, adding, updating, or removing fields as needed. No more opaque JIDs; your contacts now have a face and a name.
Per-Room Ignored Users (XEP-0223)
You can now ignore specific users on a per-room basis, with ignore lists stored server-side via Personal Eventing Protocol (XEP-0223). Filtering has been improved to cross-match JIDs and occupant IDs, and notifications from ignored users (including quoted replies) are now properly suppressed.
Contact Management from the Room
A new contact management dropdown in the occupant sidebar and a dedicated contact addition button in the profile screen make it easy to manage your contact list without leaving the conversation. Right-clicking (or long-pressing) a nickname in room messages now brings up an occupant context menu with quick actions.
Quality of Life
Entity Time (XEP-0202) — see your contact&aposs local time in the chat header and contact popover, handy for distributed teams.
Message delivery errors are now displayed inline, with the option to retry sending directly.
Do Not Disturb mode now suppresses sound and desktop notifications automatically.
Font size setting added to appearance preferences.
Avatar lightbox — click an avatar in message view to see it full-size.
PEP-based conversation list sync (ConversationSync module) keeps your sidebar consistent across sessions.
External links now open in a Tauri webview popup instead of jumping to the system browser.
Full-screen occupant panel on small screens for a better mobile experience.
Bug Fixes & Reliability
This release addresses a significant number of issues:
Active rooms now correctly move to the top of the sidebar on new messages
Missing room messages after reconnect or app restart
Blank window in MUC rooms caused by a stale ResizeObserver
Reactions UI properly enabled in rooms with stable occupant identity
Native window theme now syncs correctly with system mode in Tauri
Modals no longer close when click-dragging from inside to outside
Fixed: owner showing as moderator in the chat view
The Ignite Realtime community is happy to announce a new release of its open source, real-time communications server server Openfire! Version 5.0.4 continues our effort to provide stable 5.0.x series releases whilst we finalize work on an upcoming 5.1.0 release. Please refer to the full changelog for more details.
You can obtain the new version of Openfire for your platform from its download page. The sha256sum values for the release artifacts are: