Planet Jabber

May 13, 2025

Erlang Solutions

Common MVP mistakes: How to build smart without overbuilding

A Minimum Viable Product (MVP) is your first real signal to the market, your team, and your investors that you’re solving the right problem in the right way. While it’s often mentioned alongside terms like Proof-of-Concept (PoC), prototype, or pilot, an MVP plays a distinct role: validating real value with real users.

Avoiding common missteps early sets the stage for faster iteration, smarter growth, and long-term success. Startups are under pressure to move quickly, but speed without focus can lead to costly mistakes. Proving value fast is essential, especially with limited resources, but moving too quickly without the right foundation can stall progress just as easily as moving too slowly.

What an MVP should be

An MVP is the leanest version of your product that still delivers real value and helps you learn whether you’re solving the right problem. 

It’s not about perfection, but validation. Will users care enough to try, pay, or share? 

Importantly, a strong MVP also signals to investors that you can efficiently test ideas, understand your market, and move fast with limited resources.

Focus on what matters, build with intent, and treat your MVP not as a throwaway prototype, but as the foundation of everything to come.

Small by design, smart by strategy

Popularised by Eric Ries in The Lean Startup, the MVP is designed to reduce wasted time, money, and effort. By building only what’s needed to test your core assumptions, you can learn quickly and adjust early, before burning through too much time, money, or energy.

A good MVP doesn’t just mean “basic”

A strong MVP isn’t just a stripped-down prototype. It’s the foundation of your product. Lightweight, but also reliable, secure, and built for change. If it can’t be used, demoed, or trusted, it’s not doing its job.

Focus on what matters, build with intent, and treat your MVP not as a throwaway prototype, but as the foundation of everything to come.

Minimise risk, maximise learning

An MVP helps you move fast and stay focused. It’s not about trial and error. It’s about proving your idea works and showing investors that you’re building something ready to grow.

Common MVP mistakes (and how to avoid them)

Building an MVP is about speed and learning. But moving fast shouldn’t mean skipping the fundamentals. Many startups fall into familiar traps: doing too much too soon, choosing the wrong tools, or cutting corners that cause problems later.

By spotting these mistakes early, you can build smarter, avoid rework, and give your product a better chance of success.

Overbuilding Before Validation

Adding too many features at the start slows you down, increases costs, and weakens your core value. A bloated MVP is harder to test, more expensive to maintain, and often confusing for users.

Why it happens:

  • Unclear priorities
  • Perfectionism
  • Fear of missing out

How to avoid it:

Focus on solving one clear problem well. Use low-code or no-code tools to test ideas quickly without overcommitting time or budget.

Choosing the wrong tech stack

Selecting technology based on trends instead of fit creates long-term issues. The wrong stack can lead to expensive rebuilds, poor stability, development slowdowns, and scaling challenges.

Why it matters:

Your tech choices affect how fast you can iterate, how well you scale, and how easy it is to adapt later.

How to avoid it:

Choose a simple, flexible stack that fits your domain. Use tools that support rapid development and long-term growth. Involve technical partners or advisors with experience to help avoid common mistakes.

Ignoring security and code quality

When speed trumps structure, the result is often messy, unreliable code.

A growing trend, vibe coding, uses AI (especially large language models) to quickly generate code from natural language. While this accelerates initial progress, it often skips testing, documentation, and consistency, leading to hidden risks and technical debt. 

Though fast at first, vibe coding can leave fragile code that’s hard to debug, extend, or transfer, with teams diverging in approach and progress stalling over time.

Why does it happen?

  • Misunderstanding MVP as “low quality” rather than “focused and efficient”
  • Overreliance on AI-generated code without review or standards
  • Lack of experienced engineering oversight

Risks include:

  • System instability and hidden failures
  • Security vulnerabilities and compliance breaches
  • Technical debt and poor maintainability
  • Loss of trust from investors and partners

How to avoid it:

Prioritise quality from day one:

  • Review AI code for security, clarity, and maintainability
  • Apply secure authentication and data encryption
  • Set shared coding standards and style guides
  • Require basic tests and documentation, even for MVPs
  • Limit LLM use in critical paths unless thoroughly validated
  • Track shortcuts and log them as technical debt to resolve later

A little rigour early on prevents major setbacks down the line.

What smart MVP development looks like

A smart MVP is fast, focused, and built for flexibility. It doesn’t aim to include everything, just enough to test your core idea with real users.

Here’s what that looks like in practice:

Built fast, not rushed

Speed should serve as validation. The best MVPs reach users quickly without creating confusion or technical debt.

Focus on:

  • Delivering one clear value
  • Releasing early to gather feedback
  • Improving in tight, focused cycles

Easy to change, because feedback is coming

A smart MVP is flexible by design. Once feedback starts coming in, you need to be ready to adjust quickly without overhauling everything.

Make this easier with:

  • Modular code
  • Clear documentation
  • A prioritised backlog for fast iteration

Safe and secure – even if it’s lean

Even a small MVP needs to be stable and secure. If users are testing it, they’re trusting it. 

Trust depends on:

  • Data security and privacy (including GDPR compliance)
  • A clear, usable interface
  • Consistent, reliable performance

A strong MVP is:

  • Right-sized: Solves one problem well
  • Stable: Works reliably in demos and tests
  • Scalable: Built on a foundation that can grow
  • Trustworthy: Respects and protects user data

Smart MVP development means building fast, but building right. When you combine speed with strategy, you don’t just ship faster, you learn faster, improve faster, and grow stronger.

Build fast. Build smart. Build for growth.

A strong MVP helps you validate your idea, attract early users or investors, and gather feedback, without overbuilding or overspending. The goal is not just to launch quickly, but to launch with clarity, purpose, and scalability in mind.

Many teams fall into the same traps: bloated feature sets, the wrong technology choices, or neglecting long-term costs. These missteps waste time, burn cash, and kill momentum. The most effective MVPs are built with focus, tested against the right assumptions, and grounded in a foundation that supports growth from day one.

At Erlang Solutions, we can help your startup launch MVPs that are resilient under pressure and built for the future. If you’re ready to build something that works, let’s talk.

The post Common MVP mistakes: How to build smart without overbuilding appeared first on Erlang Solutions.

by Erlang Solutions Team at May 13, 2025 10:35

May 05, 2025

The XMPP Standards Foundation

The XMPP Newsletter April 2025

XMPP Newsletter Banner

XMPP Newsletter Banner

Welcome to the XMPP Newsletter, great to have you here again! This issue covers the month of April 2025.

Like this newsletter, many projects and their efforts in the XMPP community are a result of people’s voluntary work. If you are happy with the services and software you may be using, please consider saying thanks or help these projects! Interested in supporting the Newsletter team? Read more at the bottom.

XSF Announcements

XSF Membership

If you are interested in joining the XMPP Standards Foundation as a member, submissions are open until May 18th, 2025, 00:00 UTC!.

XSF Fiscal Hosting Projects

The XSF offers fiscal hosting for XMPP projects. Please apply via Open Collective. For more information, see the announcement blog post. Current projects you can support:

XMPP Events

  • Berlin XMPP Meetup [DE / EN]: monthly meeting of XMPP enthusiasts in Berlin, every 2nd Wednesday of the month at 6pm local time.
  • XMPP Italian happy hour [IT]: monthly Italian XMPP web meeting, every third Monday of the month at 7:00 PM local time (online event, with web meeting mode and live streaming).
  • XMPP Sprint in Berlin: On Friday, 23rd, Saturday, 24th, and Sunday, 25th of May 2025.

XMPP Articles

XMPP Software News

XMPP Clients and Applications

  • Cheogram has released version 2.17.10-1 for Android. This version introduces an initial implementation of Spaces (XEP-503), among other improvements, bugfixes and more!
  • Conversations has released versions 2.18.0, 2.18.1 and 2.18.2 for Android. Notable changes include the ability to pick a custom backup location, a prominent backup restore option for Quicksy, and improved support for more kinds of URIs. The latter includes tel phone numbers, mailto email addresses, and more interestingly the web+ap scheme for ActivityPub proposed by Fedi Links.
  • Dino has released version 0.5 featuring OMEMO encryption by default, improved file transfers, image preview and other file details before downloading, and two completely reworked dialogs. See the release blog post for all the details.
    • At the same time, Dino has also received funding from NLnet to begin development on a slew of new features. This includes message moderation in group chats, local message deletion, modern connection handling with FAST and SASL2, more formatting options with Message Markup, and more! Visit the project page for all the details.
  • Gajim has released versions 2.1.0 and 2.1.1 with a new ‘Activity feed’ page, layout improvements for its ‘Start Chat’ dialog and support for ‘Message Display Synchronisation’ (XEP-0490) across group chats among other improvements and bugfixes. Head over to their News section for all the details.
Activity feed in Gajim 2.1

Activity feed in Gajim 2.1

Account and status selection in Gajim 2.1

Account and status selection in Gajim 2.1

  • Kaidan has received NLnet funding for various improvement across the board, most notably multi-user chat and support for legacy OMEMO. The second point is significant because while Kaidan is using a newer version of the OMEMO end-to-end encryption protocol, other popular clients including Conversations, Monal, and Dino are still using an older version. Since the two are not compatible, this meant Kaidan users were unable to use OMEMO encryption with users of most other clients. By implementing the older spec as well, Kaidan will help bridge that gap.

  • Monocles Chat 2.0.6 has been released for Android. This version brings initial support for file captions, the option to pin an unencrypted message to the top of a conversation, providers list support, and the option to register on your own XMPP server, among many other new features and improvements.

Monocles Chat 2.0.6: Initial captions to files and pin message to the top

Monocles Chat 2.0.6: Initial captions to files and pin message to the top

Monocles Chat 2.0.6: Register on your own XMPP server or pick one from the providers list

Monocles Chat 2.0.6: Register on your own XMPP server or pick one from the providers list

  • Movim has released version 0.30 (code named “Encke”), the biggest Movim evolution in many years! This release brings multi-participant calls, reactions being displayed in the detailed message view, support for Unicode 15.1 with plenty of new emojis to use, and avatars that change when a contact adds to their Story.
Movim 0.30 (Encke): Multi Participant Calls. Bob Cat looking disgruntled by the presence of the ‘Hooman’ on the lower right of the screen!

Movim 0.30 (Encke): Multi Participant Calls. Bob Cat looking disgruntled by the presence of the ‘Hooman’ on the lower right of the screen!

Movim 0.30 (Encke): Meow OwO bedazzled by the looks of Multi Participant Calls on his mobile device!

Movim 0.30 (Encke): Meow OwO bedazzled by the looks of Multi Participant Calls on his mobile device!

  • and following right on its heels, Movim also published its first bug-fix release: version 0.30.1, adding animated pictures support in the image proxy and a new Avatar and Banner Configuration Panel, as well as implementing (XEP-0392) Consistent Color Generation, among many other improvements and bugfixes. Make sure to check out the official announcements at the Movim Blog for all the details!
Movim 0.30.1: Avatar and banner configuration panel

Movim 0.30.1: Avatar and banner configuration panel

XMPP Servers

  • MongooseIM has released version 6.3.3 of its Enterprise Instant Messaging Solution. This minor update includes various fixes and improvements. For more information, check out the documentation.
  • ProcessOne has published ejabberd 25.04. This release brings an important security fix, several bug fixes and a new API command.
  • Prosody IM is pleased to announce version 13.0.1, a new minor release from the latest stable branch. It fixes some important bugs that were discovered after the latest release. Read all the details on the release changelog. As always, detailed download and install instructions are available on the download page for your convenience.
  • The Prosody app for YunoHost has been updated to provide a bunch of supported XEPs by default, configured for all YunoHost users in just one click. YunoHost is a set of tools to easily manage your own selfhosted services, and while it used to come bundled with the Prosody fork Metronome by default, it has recently bundled its XMPP functionality into a separate “app” so that people can swap in any other XMPP server of their choice.

XMPP Libraries & Tools

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.

  • No XEPs proposed this month.

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.

  • No XEPs deferred this month.

Updated

  • Version 1.1.3 of XEP-0313 (Message Archive Management)
    • Fixed typo (XEP Editor (dg))
  • Version 0.4.0 of XEP-0377 (Spam Reporting)
    • Add spam report processing opt-in.
    • Add Guus der Kinderen as co-author. (gdk)
  • Version 1.0.1 of XEP-0421 (Occupant identifiers for semi-anonymous MUCs)
    • Fixed typo (XEP Editor (dg))
  • Version 0.3.0 of XEP-0455 (Service Outage Status)
    • Remove all in-band event signaling. (mp)

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.

  • No Last Call this month.

Stable

  • No XEPs moved to Stable this month.

Deprecated

  • No XEPs deprecated this month.

Rejected

  • No XEPs rejected this month.

Spread the news

Please share the news on other networks:

Subscribe to the monthly XMPP newsletter
Subscribe

Also check out our RSS Feed!

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):

  • English (original): xmpp.org
    • General contributors: Adrien Bourmault (neox), Alexander “PapaTutuWawa”, Arne, Badri Sunderarajan, Benson Muite, cal0pteryx, emus, Federico, Gonzalo Raúl Nemmi, Jonas Stein, Kris “poVoq”, Licaon_Kter, Ludovic Bocquet, Mario Sabatino, melvo, MSavoritias (fae,ve), nicola, Schimon Zachary, Simone Canaletti, singpolyma, XSF iTeam
  • French: jabberfr.org and linuxfr.org
    • Translators: Adrien Bourmault (neox), alkino, anubis, Arkem, Benoît Sibaud, mathieui, nyco, Pierre Jarillon, Ppjet6, Ysabeau
  • Italian: notes.nicfab.eu
    • Translators: nicola
  • Spanish: xmpp.org
    • Translators: Gonzalo Raúl Nemmi
  • German: xmpp.org
    • Translators: Millesimus
  • Português (BR): xmpp.org
    • Translators: Paulo

Help us to build the newsletter

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

To unsubscribe from this list, please log in first. If you have not previously logged in, you may need to set up an account with the appropriate email address.

License

This newsletter is published under CC BY-SA license.

May 05, 2025 00:00

May 01, 2025

Erlang Solutions

Looking Forward to ElixirConf EU 2025

ElixirConf EU 2025 is only two weeks away! Soon, it will once again be time for the Elixir community from Europe and beyond to come together, connect, and learn from each other about Elixir and its ecosystem. There will be dozens of talks from speakers across the community, training opportunities, and more.

This year’s event is being held in Kraków, Poland from May 15-16, with optional training available on May 14. Both in-person and virtual tickets are available.

Here’s a preview of some of the speakers on the schedule, and what to expect from their talks:

Keynotes

José Valim: Type System and Elixir Updates

No ElixirConf would be complete without an appearance from Dashbit’s José Valim, the creator of Elixir.


Since announcing it at ElixirConf EU 2022, José and the Elixir team have been hard at work on a type system for the language based on set-theoretic types. Implementation of this system is still underway, and José will offer an update on its progress, as well as other recent activities from the Elixir team and what to expect in the next release. Guillaume Duboc, a PhD student at Université Paris Cité who is working on the type system for his thesis, will provide a more in-depth look at it in a separate talk, “What’s New with Elixir Types”.

James Arthur: Introducing Phoenix.Sync

James Arthur is a TED Prize and Microsoft Prize-winning co-founder of Opendesk, Hazy, and Post Urban, with prior software development experience for Apple and IDEO.

He is currently the CEO of ElectricSQL, developers of the Elixir sync engine Electric, and will be bringing that knowledge to his keynote introducing Phoenix.Sync, a new library that adds real-time sync to Phoenix. Expect a tour through the basics of the library, how to use it to sync data into both backend and frontend applications, and its potential uses in AI systems.

Davide Bettio and Mateusz Front: The AtomVM and New Horizons for Elixir

SECO Mind’s Davide Bettio has years of embedded systems and IoT experience, and began work on AtomVM, a lightweight BEAM implementation tailored for IoT devices, in 2017.

He’ll be joined by Mateusz Front, an Elixir developer at Software Mansion, to explain the results of a collaboration that has proved Elixir can be run on a whole new platform. They’re keeping quiet about the specifics, so you’ll have to check out their keynote to find out what they’ve come up with, along with plenty more information about AtomVM and Elixir runtimes.


Industry Stories

Anita Ludermann: Turn Old Into New: Moving to Elixir Feature by Feature

Anita Ludermann is a software engineer currently at Modell Aachen GmbH, where she has spent the last few years working with a team whose goal is to modernise a legacy codebase by transitioning it to Elixir.

She’ll be offering a first-hand account of what adoption of Elixir and the functional paradigm in general looks like in a real-world industry context, with all the challenges of shifting an entire system to a new language bit by bit while maintaining consistent functionality for the user.

Ettore Berardi: How Elixir Powers the BBC: From PoC to Production at Scale

After a stint at MacMillan Science and Education, Ettore Berardi joined the BBC, where he has now been working for eight years as a tech lead.

He’ll be relaying another story of Elixir adoption in action, namely the four-year process of shifting to Elixir at the BBC, starting with an initial proof of concept and culminating with nearly all BBC app and web traffic being served by Elixir. On top of the technical side of things, he’ll also discuss the realities of building and maintaining Elixir expertise in an environment largely unfamiliar with the language.

Libraries and Frameworks

Gus Workman: Introducing Trellis: Open Source Hardware for Nerves

You may already be familiar with Nerves, a framework for using Elixir to build embedded systems. Gus Workman is the founder of Protolux Electronics, a company specialising in Nerves-based hardware and software.

His talk will introduce Trellis, an open-source hardware platform reminiscent of Raspberry Pi, but specifically built with the purpose of producing custom circuit boards for Nerves and Elixir.

Parker and Shannon Selbert: The Architecture of Oban Web

Oban Web, the live dashboard for the prominent Elixir background job library Oban, recently became fully open source.

Now, Oban’s creator Parker Selbert and Oban core team member Shannon Selbert, co-founders of Soren, will be diving into the internals of the project, touring its key elements and interesting features. They promise to reveal how to structure a complex LiveView application with extensive real-world use, backed by Oban Met, a purpose-built distributed database.

Ridwan Otun and Sola-Aremu ‘Pelumi: Whisperer: An Elixir-Based Multi-Agent Framework

Ridwan Otun and Sola-Aremu ‘Pelumi are two self-described Elixir evangelists working as engineering vice presidents at Juicyway and Bank of America, respectively.
Their talk will introduce Whisperer, a new and recently open-sourced framework that allows users to define, sequence, and orchestrate multi-agent AI systems. It’s another talk that’s well worth checking out if you’re interested in learning how Elixir developers are taking advantage of the new possibilities afforded by agents and LLMs.

Deep Dives

Conor Sinclair: Meta-Programming in Elixir: Dynamic Function Calling with LLMs

Multiverse’s Conor Sinclair is a senior software engineer specialising in frontend and with a passion for Elixir.

 He’ll be joining the conference to address the now-ubiquitous topic of LLMs. Conor will be addressing Elixir specifically, walking the audience through the process of creating generic interfaces and using the Langchain library to expose them to LLMs. It’s sure to be a fascinating talk for anyone curious as to how these models interface with an existing application.

Robert Virding: Unveiling the Magic of Erlang/OTP Behaviours: A Deep Dive in the Codebase & Björn Gustavsson: My Beam History

We’ll also be getting talks from two developers whose experience with Erlang and the BEAM goes back to the very beginning. Robert Virding was one of the co-creators of Erlang at Ericsson, and now works for Erlang Solutions as Principle Language Expert.
He’ll be offering a deep dive into the Erlang/OTP codebase, as well as a BEAM VM training session the day before the conference proper. Björn Gustavsson, meanwhile, joined the OTP team in 1996 and later became the main developer for the BEAM, which is partially named for him. His talk will explore his three decades of history with the BEAM.

And More!

Of course, that’s only a fraction of the talks at this year’s event – there are plenty of others, and it’s worth checking out the full list of speakers to see if there’s anything else that catches your eye. If you’ve already committed to attending, the schedule is now available, so you can start deciding which talks to attend.

There’s sure to be something for everyone with an interest in Elixir and the BEAM, and Erlang Solutions will be present at the event as always, so be sure to say hi to our team if you do attend. We hope to see you in Kraków in a few weeks for ElixirConf EU 2025!

The post Looking Forward to ElixirConf EU 2025 appeared first on Erlang Solutions.

by Rhys Davey at May 01, 2025 09:24

April 24, 2025

Erlang Solutions

Reduce, Reuse… Refactor: Clearer Elixir with the Enum Module

“When an operation cannot be expressed by any of the functions in the Enum module, developers will most likely resort to reduce/3.”

From the docs for Enum.reduce/3

In many Elixir applications, I find Enum.reduce is used frequently. Enum.reduce can do anything, but that doesn’t mean it should. In many cases, other Enum functions are more readable, practically as fast, and easier to refactor.

I would also like to discuss situations that are a good fit for Enum.reduce and also introduce you to a custom credo check I’ve created, which can help you identify places where Enum.reduce could be replaced with a simpler option.

Readability

Here are a few common reduce patterns—and their simpler alternatives.  For example, here’s something I see quite often:

Enum.reduce(numbers, [], fn i, result -> [i * 10 | result] end)
|> Enum.reverse()

This is a situation that the Enum.map function was designed for:

Enum.map(numbers, & &1 * 10)

Perhaps you know about Enum.map, but you might see a call to reduce like this:

Enum.reduce(numbers, 0, fn number, result -> (number * 2) + result end)

Let me introduce you to Enum.sum_by!


Enum.sum_by(numbers, & &1 * 2)

Let’s look at something a bit more complex:

Enum.reduce(numbers, [], fn item, acc ->
  if rem(item, 2) == 0 do
    [item * 2 | acc]
  else
    acc
  end
end)
|> Enum.reverse()

This is a perfect case for piping together two Enum functions:

numbers
|> Enum.filter(& rem(&1, 2) == 0)
|> Enum.map(& &1 * 2)

Another option for this case could even be to use Enum.flat_map:


Enum.flat_map(numbers, fn number ->
  if rem(number, 2) == 0 do
    [number * 2]
  else
    []
  end
end)

This is a decent option, but while this achieves the purpose of both filtering and mapping in a single pass, it may not be as intuitive for everybody.

Lastly, say you see something like this and think that it would be difficult to improve:

Enum.reduce(invoices, {[], []}, fn invoice, result ->
  Enum.reduce(invoice.items, result, fn item, {no_tax, with_tax} ->
    if Invoices.Items.taxable?(item) do
      tax = tax_for_value(item.amount, item.product_type)
      item = Map.put(item, :tax, tax)

      if Decimal.equal?(tax, 0) do
        {no_tax ++ [item], with_tax}
      else
        {no_tax, with_tax ++ [item]}
      end
    else
      {no_tax, with_tax}
    end
  end)
end)

But this is just the same:

invoices
|> Enum.flat_map(& &1.items)
|> Enum.filter(&Invoices.Items.taxable?/1)
|> Enum.map(& Map.put(&1, :tax, tax_for_value(&1.amount, &1.product_type)))
|> Enum.split_with(& Decimal.equal?(&1.tax, 0))


Aside from improving readability, splitting code out into pipes like this can make it easier to see the different parts of your logic.  Especially once you’ve created more than a few lines of pipes, it becomes easier to see how I can pull out different pieces when refactoring.  In the above, for example, you might decide to create a calculate_item_taxes function which takes a list of items and performs the logic of the Enum.map line.

Performance

You may have already thought of a counterpoint: when you pipe functions together, you end up creating new lists, which means more work to be done as well as more memory usage (which means more garbage collection).  This is absolutely true, and you should be thinking about this!  

But I find that 99% of the time, the data I’m working with makes the performance difference negligible.  If you find that your code is slow because of the amount of data that you need to process, you might try using the Stream module — it has many of the same functions as Enum, but works lazily.  If that doesn’t work, then by all means, create a reduce (and maybe put it into a well-named function)! 

 As Joe Armstrong said:

“Make it work, then make it beautiful, then if you really, really have to, make it fast.”

For some information about benchmarks that I’ve run to understand this better, see this analysis and discussion.

Good Opportunities for Enum.reduce

Aside from occasional performance reasons, Enum.reduce can often be the simplest solution when you want to transform a data structure over a series of steps.  For example:

Find Cases in Your Own Code with credo_unnecessary_reduce

Remember that no one pattern works in all cases, so know what tools you have available! If you’d like to quickly find instances for potential improvements in readability, I built a Credo check to help spot where reduce can be swapped for something simpler.

You can drop it into your project and start catching these anti-patterns automatically.

https://github.com/cheerfulstoic/credo_unnecessary_reduce

Simply add it to your mix.exs file:


{:credo_unnecessary_reduce, "~> 0.1.0"}

…and then enable it in your .credo.exs file:


{CredounnecessaryReduce.Check, []}

The post Reduce, Reuse… Refactor: Clearer Elixir with the Enum Module appeared first on Erlang Solutions.

by Brian Underwood at April 24, 2025 14:32

April 17, 2025

Erlang Solutions

Erlang Solutions’ Blog round-up

The tech world doesn’t slow down, and neither do we. From the power of big data in healthcare to keeping you up-to-date about fintech compliance, our latest blog posts explore the important topics shaping today’s digital world.

Whether you’re leading a business, building software, or just curious about the future of tech, check out what the Erlang Solutions team has been talking about.

Understanding Big Data in Healthcare


From smartwatches to digital patient records, healthcare is generating more data than ever before. In our post, Understanding Big Data in Healthcare, we explore how big data is transforming patient care—think predictive health trends, precision medicine, and smarter decision-making.

We also dig into the challenges of handling sensitive information and how tech like Erlang, Elixir, and SAFE can help keep that data secure. It’s a must-read if you’re curious about how data is shaping the future of healthcare.

Understanding Digital Wallets


Digital wallets aren’t just convenient, but they’re quickly becoming essential. In Understanding Digital Wallets, we break down how they work, why they’re gaining momentum, and what they mean for businesses today.

From improved security and cost savings to global access and smoother customer experiences, this blog gives a clear look at the benefits (and a few of the challenges) of going digital.

Women in BEAM

Lorena Mireles takes us through the key takeaways from her Women in BEAM survey, while also sharing her personal journey within the Elixir community.

From representation gaps to the importance of strong role models, this piece highlights real experiences from developers in the BEAM ecosystem and why inclusion still matters in tech.

Top 5 IoT Business Security Basics 

Billions of connected devices = billions of entry points for hackers. In Top 5 IoT Business Security Basics, we outline five practical tips to boost your IoT security:

  • Use strong, unique passwords
  • Encrypt your data
  • Run regular security audits
  • Train your team
  • Disable features you don’t use

Simple, effective, and easy to implement—these tips will help you keep your systems (and customers) safe.

DORA Compliance: What Fintech Businesses Need to Know


Digital Operational Resilience Act (DORA) for fintech

As of January 2025, the Digital Operational Resilience Act (DORA) is live, and if you’re in fintech, you need to be ready. Our post, DORA Compliance: What Fintech Businesses Need to Know, breaks down what DORA is, who it affects, and what steps you need to take to stay compliant (if you haven’t already).

We explore its five key pillars and how to build a more resilient, disruption-proof business. With over 22,000 companies affected, it’s a timely read for anyone in the financial space.

To conclude

Staying ahead in tech doesn’t have to be overwhelming. Our goal? To make it easier for you to understand what’s happening and what it means for your business.

Got questions? Let’s chat.

The post Erlang Solutions’ Blog round-up appeared first on Erlang Solutions.

by Erlang Solutions Team at April 17, 2025 10:27

Gajim

Gajim 2.1.1

This release brings layout improvements to Gajim’s Start Chat dialog, an improved message search, and includes fixes for some issues with Message Displayed Synchronization. Thank you for all your contributions!

What’s New

Gajim 2.1 comes with a new ‘Activity feed’ which displays events around group chat invitations, contact requests, and updates. This will be the central feed for all kinds of activities in the future (e.g. reactions, replies, mentions, message reminders).

Activity feed in Gajim 2.1

Activity feed in Gajim 2.1

Gajim 2.1.1 brings layout improvements for its Start Chat dialog, which now renders more compact and shows more information. This release also improves message search by displaying the last correction of a message and by not showing moderated messages. Last but not least, some issues with XEP-0490: Message Displayed Synchronization have been fixed.

A note for Windows users: At the time of writing, there are some issues with emoji rendering on Windows. That’s why there is no release of Gajim 2.1 for Windows yet. This issue should soon be resolved and we will post an update once Gajim 2.1 is released on Windows.

More Changes

  • Group chats now show voice request errors, if they happen
  • Setting your status for multiple accounts though the account sidebar now works properly

And much more! Have a look at the changelog for a complete list.

Gajim

As always, don’t hesitate to contact us at gajim@conference.gajim.org or open an issue on our Gitlab.

Gajim is free software developed by volunteers.
If you like to support Gajim, please consider making a donation.

Donate via Liberapay:

April 17, 2025 00:00

April 16, 2025

ProcessOne

ejabberd 25.04

ejabberd 25.04

Just a few weeks after previous release, ejabberd 25.04 is published with an important security fix, several bug fixes and a new API command.

Release Highlights:

If you are upgrading from a previous version, there are no changes in SQL schemas, configuration, API commands or hooks.

Other contents:

Below is a detailed breakdown of the improvements and enhancements:

mod_muc_occupantid: Fix handling multiple occupant-id

Fixed issue with handling of user provided occupant-id in messages and presences sent to muc room. Server was replacing just first instance of occupant-id with its own version, leaving other ones untouched. That would mean that depending on order in which clients send occupant-id, they could see value provided by sender, and that could be used to spoof as different sender.

New kick_users API command

There is a new API command kick_users that disconnects all the client sessions in a given virtual host.

Acknowledgments

We would like to thank the contributions to the source code, documentation, and translation provided for this release by:

And also to all the people contributing in the ejabberd chatroom, issue tracker...

Improvements in ejabberd Business Edition

For customers of the ejabberd Business Edition, in addition to all those improvements and bugfixes:

  • Bugfix on max_concurrent_connections for mod_gcm, mod_webhook and mod_webpush

ChangeLog

This is a more complete list of changes in this ejabberd release:

Security fixes

  • mod_muc_occupantid: Fix handling multiple occupant-id

Commands API

  • kick_users: New command to kick all logged users for a given host

Bugfixes

  • Fix issue with sql schema auto upgrade when using sqlite database
  • Fix problem with container update, that could ignore previous data stored in mnesia database
  • Revert limit of allowed characters in shared roster group names, that will again allow using symbols like :
  • Binary installers and ejabberd container image: Updated to Erlang/OTP 27.3.2

Full Changelog

https://github.com/processone/ejabberd/compare/25.03...25.04

ejabberd 25.04 download & feedback

As usual, the release is tagged in the Git source code repository on GitHub.

The source package and installers are available in ejabberd Downloads page. To check the *.asc signature files, see How to verify ProcessOne downloads integrity.

For convenience, there are alternative download locations like the ejabberd DEB/RPM Packages Repository and the GitHub Release / Tags.

The ecs container image is available in docker.io/ejabberd/ecs and ghcr.io/processone/ecs. The alternative ejabberd container image is available in ghcr.io/processone/ejabberd.

If you consider that you&aposve found a bug, please search or fill a bug report on GitHub Issues.

by Jérôme Sautret at April 16, 2025 17:21

April 15, 2025

ProcessOne

Hello from the other side: Matrix ↔ XMPP via ejabberd 25.03

Hello from the other side: Matrix ↔ XMPP via ejabberd 25.03


With ejabberd 25.03, the Matrix gateway (mod_matrix_gw) now supports not only one-to-one chats, but also joining Matrix rooms via XMPP. That’s right — your favorite XMPP client can now talk to Matrix users or hop into Matrix rooms just like regular MUCs. ✨

In this guide, we’ll show a quick demo of:

  1. One-to-one chat between an XMPP and a Matrix user.
  2. Joining a Matrix room and chatting from your XMPP client.

And the best part? You don’t need to install a Matrix client at all. Keep your favorite XMPP client near, welcome to the magic of federation & interoperability.


🛠 Setup Summary

We won’t repeat the full configuration steps here — they’re already covered in this earlier blogpost and the 25.03 release note.

In short, you’ll need:

  • A properly configured ejabberd server with mod_matrix_gw
  • Block outgoing connections to lethe.matrix.org to avoid conflicts with their XMPP instance

Here’s a minimal config snippet:

listen:
  -
    port: 8448
    module: ejabberd_http
    tls: true
    request_handlers:
      "/_matrix": mod_matrix_gw

modules:
  mod_matrix_gw:
    key_name: "xxxxxx"
    key: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    matrix_id_as_jid: true

Wondering what is the Matrix signing key? Please refer to previous blog post: Matrix gateway setup with ejabberd

Still not sure if your setup is correct? Try Matrix Federation Tester to check if everything is wired up properly.

🧪 One-to-One Chat (XMPP ↔ Matrix)

In your XMPP client (e.g. Psi), add a Matrix contact using this format:
matrixUser%theirMatrixServer.tld@yourXMPPserver.tld

In my case, that means:
adrien-p1%matrix.org@matrix.mickael.m.in-app.io

On the Matrix side (e.g. Element Web), your contact will get a request. Once accepted, you’re good to chat!

✅ Demo: XMPP user (Psi) chats with Matrix user (Element Web)

🧪 Join a Matrix Room from your XMPP Client

Alright, let’s join a public Matrix room now.

From your XMPP client, you can join any Matrix public room using this format:
#matrixRoom%theirMatrixServer.tld@yourXMPPserver.tld

We’ll use the following room: #ejabberd-demo:matrix.org, so in my case, that means joining:
#ejabberd-demo%matrix.org@matrix.mickael.m.in-app.io

Once connected, you’ll be able to send and receive messages from any other participant, just like in a regular MUC. :)

✅ Demo: Join and chat in a Matrix room from XMPP

🐞 Known Caveats

There&aposs still a lot of work to do to make it seamless, here&aposs a short list of currently known caveats:

  • Room presence can be overwhelming in large rooms (thousands of Matrix users may appear "online").
  • No E2EE support between Matrix and XMPP — encryption must be disabled for now.
  • If the server restarts, 1-to-1 conversations must be restarted (re-added), as persistence is not implemented yet.
  • Only Matrix room protocol versions 9, 10, and 11 are supported.

🧵 Wrapping Up

With this, ejabberd makes another step into being a powerful bridge into the Matrix federation, for both private and public communication.

It’s a great way to keep using your favorite XMPP tools while staying connected to Matrix communities.

Got feedback? Drop us a line in the comments or open a PR.

Happy bridging! 🙌

by Adrien at April 15, 2025 13:10

April 11, 2025

Dino

Dino 0.5 Release

Dino is a secure and open-source messaging application. It uses the XMPP (Jabber) protocol for decentralized communication. We aim to provide an intuitive and enjoyable user interface.

The 0.5 release improves the user experience around file transfers and includes two completely reworked dialogs.

Improved file sharing

The way file transfers are currently done in the XMPP ecosystem is limited in functionality and files can sometimes be received out-of-order. Dino now supports a new method for announcing file transfers (XEP-0447), which solves this issue. Additionally, users can now see preview images or other file details before downloading the file. Dino currently only uses the new method for unencrypted file transfers, for example in public channels. Encrypted file transfers will also support the new protocol once Dino supports full-stanza encryption. All file transfers now also display the upload or download progress.

Screenshots of three dialogs for account settings, encryption and contact details

Reworked dialogs

The account and preferences dialogs have been combined into a single, new dialog. This dialog lets you manage accounts and adjust encryption and other settings. It now also includes some new settings like an option for OMEMO encryption by default, which is enabled by default.

Additionally, the conversation details dialog has been completely redesigned. Both dialogs are now fully compatible with mobile devices.

Colors and more

Dino now uses the same fallback avatar colors as other clients (XEP-0392), creating a more consistent experience across applications.

A new unread line has been added, indicating the point up to which you’ve already read the messages.

Dino has also switched from CMake to Meson, which allows for an easier development process.

Alentejo

We named this Dino release “Alentejo” after a region in Portugal.

Alentejo is a region in southern Portugal that is known for its wide plains that are dotted with wineyards and cork trees. The region has a Mediterranean climate with summers regularly reaching temperatures above 40 degrees.

Currently, about 3.6% of all deaths in the region are caused by heat. Heatwaves, in particular, pose a serious health risk and are expected to become more frequent and severe due to global warming [1]. If CO₂ emissions keep increasing, heat-related deaths could make up 15.8% of all deaths in the region by 2100. However, if action is taken to combat climate change, this number could be limited to 6.6% [2].

April 11, 2025 16:30

Ignite Realtime Blog

New releases for Tinder and Whack!

The IgniteRealtime community is happy to announce releases for two of its projects! Both are for XMPP-libraries that we produce.

Tinder is a Java based XMPP library, providing an implementation for XMPP stanzas and components. Tinder’s origins lie in code that’s shared between our Openfire and Whack implementations. The implementation that’s provided in Tinder hasn’t been written again from scratch. Instead, code has been moved from the original projects into Tinder, preserving al of the existing features and functionality.

The v2.1.0 release of Tinder is a maintenance release. It updates various libraries that are used by Tinder, and removes deprecated, unused code. Tinder now requires Java 11 or later. The full list of changes in this release can be found in the release notes.

Whack is a Java library that easily allows the creation of external components that follow the XEP-0114: Jabber Component Protocol. This library allows you to create server-sided components of your XMPP network that can run as stand-alone processes. That’s particularly useful when you are creating functionality for which scalability configuration differs from that of Openfire, or if you want to re-use your component for XMPP servers other than Openfire!

The v3.0.0 release of Whack is a maintenance release. It improves reconnection logic (when connection to the XMPP server is lost), it no longer ships with an embedded webserver (that was old, unused, and was raising vulnerability warnings, and updates some libraries (such as Tinder) to more recent versions. The fulll list of chagnes in this release can be found in the release notes.

We would love to hear from you! If you have any questions, please stop by our community forum or our live groupchat.

For other release announcements and news follow us on Mastodon or X

1 post - 1 participant

Read full topic

by guus at April 11, 2025 09:53

April 10, 2025

Erlang Solutions

Elixir for Business: 5 Ways It Transforms Your Processes

Elixir is a lightweight, high-performance programming language built on the Erlang virtual machine. It’s known for its simple syntax and efficient use of digital resources. But how does this translate to business benefits?

Elixir is already powering companies like Discord and Pinterest. It helps businesses reduce costs, improve process efficiency, and speed up time to market.

Here are five reasons why Elixir is a game-changer for your business.

1. Cleaner Code, Faster Progress

Elixir is designed for simplicity. Its clean syntax and functional style help developers write concise, readable code, with fewer bugs and less overhead.

For teams, this means faster development cycles and smoother collaboration. For businesses, it means shorter time to market and reduced long-term maintenance costs, which is especially useful during talent shortages.

Projects move faster when your team isn’t fighting complexity.

2. Built-In Concurrency, Built-In Stability

Concurrency – the ability to run multiple tasks at once -is essential for modern applications. Elixir handles this natively, thanks to the Erlang virtual machine it runs on.

With Elixir, you can run millions of lightweight processes simultaneously. It’s ideal for:

  • Real-time systems (e.g., messaging, live data feeds)
  • Applications with high user demand
  • Businesses that can’t afford downtime

Crucially, these processes run independently. If one fails, the rest carry on — making your application more resilient by design.

3. Smarter Use of Resources

Elixir is resource-efficient. As your infrastructure scales, Elixir adapts automatically using the processing power available.

This has clear benefits:

  • No wasted server capacity
  • Better app performance on existing infrastructure
  • Lower hosting and scaling costs

Your tech stack runs leaner and more efficiently, with fewer surprises at scale.

4. Elixir means simple scalability

Elixir was made for scalable systems. Its lightweight processes and distributed architecture allow your application to grow without rewriting core components.

What sets it apart:

  • Seamless horizontal scaling across machines
  • High fault tolerance through process isolation
  • Built-in support for distributed systems

This makes Elixir especially strong for digital products that need to scale quickly or support unpredictable usage.

Take Bleacher Report. They switched from Ruby to Elixir and saw results:

Bleacher report Elixir

  • Server count dropped from 150 to 8
  • The app now handles over 200 million push notifications a day
  • Performance improved, with far fewer bottlenecks

All of this was achieved while reducing infrastructure overhead.

Read the full case study here.

Modern Tools for Modern Challenges

Elixir isn’t just fast it’s current.

It supports distributed teams, integrates with today’s tools, and works well alongside other languages and frameworks.

It’s especially useful for:

  • Products that need to ship fast and scale cleanly
  • Teams juggling real-time features, analytics or event-driven systems
  • Organisations focused on reliability and long-term performance

Unlike many programming languages, Elixir is both powerful and practical.

To conclude

Elixir helps teams move quickly, handle growth with ease, and build reliable systems without unnecessary complexity. For modern businesses building digital platforms, it’s a quiet powerhouse and a strong strategic choice.

Want to learn more about Elixir? Explore the full “What is Elixir?” post.

Want to discuss how Elixir can enhance your business performance? Get in touch with the team.

The post Elixir for Business: 5 Ways It Transforms Your Processes appeared first on Erlang Solutions.

by Erlang Solutions Team at April 10, 2025 11:07

April 08, 2025

Gajim

Gajim 2.1.0

This release brings an all-new activity feed and adds support for Message Displayed Synchronization across group chats. Thank you for all your contributions!

What’s New

Gajim 2.1 comes with a new page called ‘Activity feed’. Currently, it displays events around group chat invitations, contact requests, and updates. Clicking an event allows you to act on it (e.g. accept an invitation) A badge indicates new activities on the top left corner of Gajim’s window. This will be the central feed for all kinds of activities in the future (e.g. reactions, replies, mentions, message reminders).

Activity feed in Gajim 2.1

Activity feed in Gajim 2.1

If you have more than one account enabled in Gajim, accounts will now be displayed inside a menu available at the bottom left corner of the window. A left click brings you to your account, while a right click allows your to set your status.

Account and status selection in Gajim 2.1

Account and status selection in Gajim 2.1

When following large group chats across multiple devices, you’ve probably experienced this: You read all new messages on one device, and later you switch to another device, but all those messages you’ve already read are now shown as unread messages. Seeing if you have read messages on another device is now supported by Gajim through XEP-0490: Message Displayed Synchronization. This feature is also supported by Conversations on Android for example. Thanks @nicoco for contributing to this feature!

A note for Windows users: At the time of writing, there are some issues with emoji rendering on Windows. That’s why there is no release of Gajim 2.1 for Windows yet. This issue should soon be resolved and we will post an update once Gajim 2.1 is released on Windows.

More Changes

  • Status icon: Fixed showing menu correctly
  • Emoji chooser: Fixed segfault after choosing emoji, which occurred on some systems
  • Nickname: Fixed displaying published nickname correctly
  • Start chat: Added ‘Execute Command…’ menu item
  • Removed unread message confirmation dialog at shutdown

And much more! Have a look at the changelog for a complete list.

Gajim

As always, don’t hesitate to contact us at gajim@conference.gajim.org or open an issue on our Gitlab.

Gajim is free software developed by volunteers.
If you like to support Gajim, please consider making a donation.

Donate via Liberapay:

April 08, 2025 00:00

April 05, 2025

The XMPP Standards Foundation

The XMPP Newsletter March 2025

XMPP Newsletter Banner

XMPP Newsletter Banner

Welcome to the XMPP Newsletter, great to have you here again! This issue covers the month of March 2025.

Like this newsletter, many projects and their efforts in the XMPP community are a result of people’s voluntary work. If you are happy with the services and software you may be using, please consider saying thanks or help these projects! Interested in supporting the Newsletter team? Read more at the bottom.

XSF Announcements

The XMPP Standards Foundation published an Open Letter to urge Meta to adopt XMPP for messaging interoperability. It’s time for real interoperability. Let’s make it happen.

XSF Membership

If you are interested in joining the XMPP Standards Foundation as a member, please apply until May 18th, 2025, 00:00 UTC!.

XSF Fiscal Hosting Projects

The XSF offers fiscal hosting for XMPP projects. Please apply via Open Collective. For more information, see the announcement blog post. Current projects you can support:

XMPP Events

  • XMPP Track at FOSSY: Call for proposals is open until April 28th 2025! Once again this year, the soprani.ca project is pleased to announce its annual offer for funding to the potential attendees who may be struggling with financial limitations, especially to those who would like to give an XMPP related talk. Please, join us at discuss@conference.soprani.ca, and don’t hesitate to ask for more information.
  • Berlin XMPP Meetup [DE / EN]: monthly meeting of XMPP enthusiasts in Berlin, every 2nd Wednesday of the month at 6pm local time.
  • XMPP Italian happy hour [IT]: monthly Italian XMPP web meeting, every third Monday of the month at 7:00 PM local time (online event, with web meeting mode and live streaming).
  • XMPP Sprint in Berlin: On Friday, 23rd, Saturday, 24th, and Sunday, 25th of May 2025.

Talks

XMPP Articles

XMPP Software News

XMPP Clients and Applications

  • Gajim has released versions 2.0.1, 2.0.2, 2.0.3 and 2.0.4 with improvements and bug fixes. Head over to their News section for all the details.
  • Kaidan has released versions 0.12.0, 0.12.1 and 0.12.2. These versions bring user interface polishing, account migration fixes, voice message and password change fixes, message removal and bubble fixes, along with more bugfixes. Check the changelog for each respective version here, here and here for all the details.
  • Poezio has released versions 0.15.0 and 0.15.1 of their console XMPP client. Detailed information available on the release announcement.
  • Profanity has released version 0.15.0 of their console based XMPP client. After more than a year and a half in the making, this release packages a large list of new features, improvements, bug fixes and more. You can find a detailed list of changes for this release on their changelog.
  • prose-web-app has released versions 0.6.2 and 0.7.0 of its Web implementation of the Prose app.

XMPP Servers

  • ProcessOne is pleased to announce the release of ejabberd 25.03: a big release with new features and many improvements, as it comes three months and 180 commits after ejabberd 24.12.
  • Prosody IM is pleased to announce the release of version 13.0.0, the new major release of the Prosody XMPP server. This release brings a wide range of improvements that make Prosody more secure, performant, and easier to manage than ever before. Read about all the details on the release changelog. As always, detailed download and install instructions are available on the download page for your convenience.

XMPP Libraries & Tools

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.

  • No XEPs proposed this month.

New

  • Version 0.1.0 of XEP-0503 (Server-side spaces).
    • Promoted to Experimental (XEP Editor: 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.

  • No XEPs deferred this month.

Updated

  • No XEPs updated this month.

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.

  • No Last Call this month.

Stable

  • No XEPs moved to Stable this month.

Deprecated

  • No XEPs deprecated this month.

Rejected

  • No XEPs rejected this month.

Spread the news

Please share the news on other networks:

Subscribe to the monthly XMPP newsletter
Subscribe

Also check out our RSS Feed!

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):

  • English (original): xmpp.org
    • General contributors: Adrien Bourmault (neox), Alexander “PapaTutuWawa”, Arne, Benson Muite, cal0pteryx, emus, Federico, Gonzalo Raúl Nemmi, Jonas Stein, Kris “poVoq”, Licaon_Kter, Ludovic Bocquet, Mario Sabatino, melvo, MSavoritias (fae,ve), nicola, Schimon Zachary, Simone Canaletti, singpolyma, XSF iTeam
  • French: jabberfr.org and linuxfr.org
    • Translators: Adrien Bourmault (neox), alkino, anubis, Arkem, Benoît Sibaud, mathieui, nyco, Pierre Jarillon, Ppjet6, Ysabeau
  • Italian: notes.nicfab.eu
    • Translators: nicola
  • Spanish: xmpp.org
    • Translators: Gonzalo Raúl Nemmi
  • German: xmpp.org
    • Translators: Millesimus

Help us to build the newsletter

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

To unsubscribe from this list, please log in first. If you have not previously logged in, you may need to set up an account with the appropriate email address.

License

This newsletter is published under CC BY-SA license.

April 05, 2025 00:00

April 03, 2025

Prosodical Thoughts

Prosody 13.0.1 released

We are pleased to announce a new minor release from our stable branch.

As is the tradition with software, here is our first patch release following shortly behind our major 13.0.0 release announced a few weeks ago. It fixes some important bugs that were discovered after the release.

Many thanks to everyone who reported issues and helped with testing the fixes for this release. We appreciate it!

For those of you on 0.12.x who haven’t upgraded yet, skip 13.0.0 and jump straight to 13.0.1 if you can. It will be a smoother upgrade.

A summary of changes in this release:

Fixes and improvements

  • mod_admin_shell: Add debug:cert_index() command to aid debugging of automatic certificate selection
  • mod_tls: Enable Prosody’s certificate checking for incoming s2s connections (fixes #1916: Impossible to override certificate verification policy in 13.0)
  • portmanager: Multiple fixes to use correct certificates for direct TLS ports (fixes #1915)
  • net.server_epoll: Use correct connection timeout when initiating Direct TLS
  • mod_roster: Fix shell commands when a component is involved (fixes #1908: error in prosodyctl shell roster attempting to subscribe a component)
  • mod_http_file_share: Explicitly reject all unsupported ranges
  • mod_http_file_share: Fix off by one in Range response
  • mod_admin_shell, prosodyctl shell: Report command failure when no password entered (fixes #1907: prosodyctl adduser: unexpected account creation on password mismatch)

Minor changes

  • mod_storage_sql: Drop legacy index without confirmation to ease upgrades
  • util.adminstream: Fix traceback on double-close (fixes #1913: Prosody fails to completely stop while shell watch:log is active)
  • certmanager: Improve logging for all cases where certs are skipped
  • mod_tls: Collect full certificate chain validation information
  • mod_s2s: Fix error detection with newer versions of OpenSSL
  • portmanager: Add debug log message to state which certificate we end up using
  • prosodyctl check certs: Use correct hostname in warning message about HTTPS
  • prosodyctl check: Be more robust against invalid disco_items, and show warning
  • spec/tls: Add TLS/certificate integration tests
  • mod_http_file_share: Improve error reporting by using util.error more
  • core.storagemanager: Fix tests by removing an assert that upset luarocks
  • core.usermanager: Fix COMPAT layer for legacy is_admin() function
  • certmanager: Remove obsolete and verbose index log (replaced by shell command)
  • doap: Add XEP-0333, XEP-0334, XEP-0156 and mod_http_altconnect

Download

As usual, download instructions for many platforms can be found on our download page

If you have any questions, comments or other issues with this release, let us know!

by The Prosody Team at April 03, 2025 19:36

XMPP Interop Testing

Enabling Tests

Our project creates a framework that allows anyone to easily add XMPP standards compliance tests to the test phase of their build pipeline. Prior to our most recent release (version 1.5.0) a test execution would basically run all tests in the test suite. We provided an option to exclude certain tests, but in essence, the bulk of tests would execute.

This behavior is generally preferable when testing an XMPP server implementation. A benefit of exclusion-based configuration is that tests that are newly added to the test suite will automatically be picked up, without requiring a configuration change.

However, there are scenarios where it is desirable to execute only a specific set of tests, for example when:

  • testing of a server-sided component, that implements only one specification, or
  • testing a development branch in which changes are applied to only one feature.

In those scenarios, having to disable all other tests is cumbersome.

We have now made available a mechanism in which specific tests can be included. When you include tests, only the included tests are executed. These configuration is very similar to that of the exclusion of tests. You can find more information in our documentation on Selecting Tests.

Please let us know if you like the new features. We’d love to hear from you!

by Guus der Kinderen at April 03, 2025 12:04

Erlang Solutions

Elixir Tutorials

Elixir is a functional language that combines modern syntax, broad metaprogramming capabilities and the power of BEAM – Erlang Virtual Machine. It has a vast community which is constantly growing due to its resilient concurrency model and programmer-friendly approach. Our tutorials are focused on showcasing language capabilities and helping any newcomer gain enough knowledge to start actively utilising Elixir in their projects.

The basics of Elixir language

In this section, we’ll have a quick look at the core properties of the language: syntax, language conventions and principles. This should allow any programmer to have an overview of what kind of language Elixir is.

Syntax and conventions

The tables below show the most essential syntax in comparison to Python:

Data Types

ElixirPython
Numbers4
-2
1_000_000
2.3
1.4e12

4
-2
1_000_000
2.3
1.4e12
Strings“Hello”
“Interpolation: #{var}”
‘Hello’f’
Interpolation: {var}’
Booleanstrue
false
True
False
Lists[1, 2, 3][1, 2, 3]
Tuples{“banana”, 4}(‘banana’, 4)
Maps%{“key” => “value”}{‘key’: ‘value’}

Note: Elixir has a data type “atom” that does not have a direct equivalent in most of the programming languages. Atoms are constants whose values are also their names. They are denoted with a colon at the beginning, e.g. an_atom.

Operators

ElixirPython
Arithmetic1 + 2
3.4 - 5.6
7 * 8
9.01 / 2.3
div(8, 3)
rem(8, 3)
1 + 2
3.4 - 5.6
7 * 8
9.01 / 2.3
8 // 3
8 % 3
Logicaltrue and false
false or true
not true
True and False
False or True
not True
Comparison9 > 5
1.2 < 2
6 >= 6
1 <= 6.5
“Hello” == “Hello”
“Hello” != “World”
1 == 1.0
1 === 1
1 !== 1.0
9 > 5
1.2 < 2
6 >= 6
1 <= 6.5
‘Hello’ == ‘Hello’
‘Hello’ != ‘World’
1 == 1.0
String concatenation“Hello “ <> “World!”‘Hello ‘ + ‘World!’
List concatenation[1, 2, 3] ++ [4, 5, 6][1, 2, 3] + [4, 5, 6]
Variable assignmentvar = 42var = 42

Control Flow

if/elseif condition do
  “It is true”
else
  “It is false”
end
if condition:
    ‘It is true’
else:
    ‘It is false’
case/matchcase status do
  200 -> “It is ok”
  400 -> “Bad request”
  _ -> “Unknown status”
end

match status:
    case 200:
        ‘It is ok’
    case 400:
        ‘Bad request’
    case _:
        ‘Unknown status’
cond/elifcond do
  2 + 2 == 5 ->
    “False”
  2 * 2 == 5 ->
    “Also false”
  1 + 1 == 2 ->
    “This is true”
end

if 2 + 2 == 5:
    ‘False’
elif 2 * 2 == 5:
    ‘Also false’
elif 1 + 1 == 2:
    ‘This is true’
comprehensionsfor i <- 0..9, do: i * 2[i * 2 for i in range(10)]

Functions

ElixirPython
defining functionsdef add(a, b) do
  a + b
end

def add(a, b):
    return a + b
calling functionsadd(1, 2)
or
1 |> add(2)
add(1, 2)
anonymous functionsadd_fn = fn a, b -> a +
b end
add_fn.(1, 2)
add_fn = lambda a, b:
a + b
add_fn(1, 2)

Functional programming principles

Functional programming is a paradigm that has a different set of core principles and rules than imperative programming or object-oriented programming. These are some of the principles that are the most relevant in Elixir:

  • First-Class Functions – Functions are treated as values, i.e. they can be assigned to variables, passed as an argument or returned from another function. In Elixir this is done by the capture operator & with the following syntax: &<function_name>/<function_arity>, e.g. &add/2
  • Immutability – Existing data is never modified; instead, each data transformation results in creating a new structure.
  • Higher-Level Abstractions – Operations on collections are done with higher-order functions like map, filter, reduce instead of explicitly looping over them. Elixir’s pipe operator |> allows to write elegant code in this manner, e.g.: list_of_ints |> Enum.filter(&is_even/1) |> Enum.map(fn a -> a * 2 end) |> Enum.sum()
  • Recursion and comprehension – There are no loops in Elixir, only recursion and comprehension. Using tail recursion can be optimized by the compiler to avoid generating big call stacks.
  • Pattern matching – Match operator = is more powerful than a simple assignment. It allows to match data with the same shape to get smaller parts of a complex data structure or choose a case clause/function head to match the argument, e. g. {id, “label”, value} = {123, “label”, 4.2}.

Elixir’s ecosystem and tools

Any programming language wouldn’t be useful in developing software without a comprehensive set of build tools, runtime tools, libraries and frameworks. Elixir has a rich ecosystem both created by the community and derived from Erlang Virtual Machine.

Erlang VM called BEAM, is a powerful runtime environment that has been battle-tested for years and provides many essential foundations for developing software systems, such as a robust concurrency model, fault-tolerance mechanism, scalability and distribution, shell for development and debugging. Elang also has a set of basic abstractions for programmers called OTP to encapsulate runtime properties of a system like process creation and supervision.

Elixir also has a vast choice of libraries to choose for creating your project:

  • Phoenix and Phoenix LiveView – web development
  • Ecto – data mapping and language integrated queries
  • Broadway – multi-stage data processing engine
  • Nx, Axon, Bumblebee – tensor calculations and ML
  • Livebook – interactive and collaborative notebooks

You can learn more about Elixir’s ecosystem by reading our What is Elixir? post.

Elixir language tutorial for beginners

In this section, we’ll show how to install Elixir on your machine and write your first program.

Installation guides across platforms

  • MacOS – run brew install elixir
  • Linux
    • Arch Linux – run pacman -S elixir
    • Debian/Ubuntu – run sudo add-apt-repository ppa:rabbitmq/rabbitmq-erlang && sudo apt update && sudo apt install elixir erlang-dev erlang-xmerl
    • Fedora – run sudo dnf --disablerepo=’*’ --enablerepo=rawhide install elixir elixir-doc erlang erlang-doc
  • Windows
    • Download and run the Erlang installer.
    • Download and run the Elixir installer compatible with your Erlang version from the previous step. The installer is available in the “Assets” list for each Elixir release, e.g.. elixir-otp-27.exe.

Alternatively, you can use the asdf version manager to install both Erlang and Elixir. To check if you’ve installed Elixir successfully, run elixir --version in your terminal.

Step-by-step development process

For your first program, we’re going to use an Elixir script. The difference between a standard Elixir program and a script is that the latter is compiled in memory and executed right away in a single command. This is useful for learning and experimenting, and if you need a program to do a task and exit.

  1. Create a file hello_world.exs and open it in a text editor.

2. Write this line in the file: IO.puts(“Hello World!”).

a. IO is a module from a standard library that handles IO operations.

b. puts is a function from this module that prints a string on standard output.

3. Save your file.

4. Open the terminal and go to the directory with the hello_world.exs file.

5. Run your script with the following command: elixir hello_world.exs.

Advanced Elixir programming tutorial

In this section, we’ll showcase in a nutshell two more advanced topics that make Elixir stand out among other popular programming languages: the concurrency model based on message passing and how scalable and fault-tolerant systems are built in Elixir.

Processes and message passing

There are two main approaches to concurrent computing: shared memory and message passing. The first one processes exchange information by writing data into the same memory block. To keep order in this, synchronization mechanisms such as mutexes and semaphores are used. With message passing, each process is isolated, i.e. has its memory, and the communication between processes is handled by exchanging messages. The formal mathematical model for this approach is called the Actor Model.

In Elixir, each process has its Process Identifier (referred to as PID). If you want to send a message to another process, you need to have its PID and call a send function:

send(pid, "The message")

The first argument is the receiver’s PID, and the second one is the message, which can be of any Elixir data type, even complex data structure. However, getting a message does not interrupt any task that a process is doing. Instead, there is a mailbox which stores all the messages that a process receives, and then it can explicitly fetch a single one with the receive instruction:

receive do
 msg -> IO.puts("I've received: #{msg}")
end

This code sample fetches the first message in the message queue (i.e. the one that came the earliest) and prints it on standard input. The whole operation can be visualized with the following diagram:

Elixir code sample diagram

But how do you get a process’s PID in the first place? To create a new process, you need to call the spawn function with the function that this process will execute, and the return value is its PID. You can also call a self function to get the PID of a current process. The following example showcases how bidirectional communication can be achieved:

# Function to be executed by the new process
def multiply_by_two() do
 receive do
   {reply_to, val} -> send(reply_to, val * 2)
 end
end


# Getting PID of process A
pid_a = self()
# Creating process B
pid_b = spawn(&multiply_by_two/0)


# Sending a message to process B
send(pid_b, {pid_a, 2})
# Receiving a message from process B
receive do
 val -> IO.puts("Result: #{val}")
end


There are many topics beyond the scope of this article regarding concurrency in Elixir: monitoring other processes, linking processes, registering a process under a global name and abstractions for building processes in OTP. However, this example should give a glimpse of what the core foundation for concurrency in Elixir is.

Fault tolerance and scalability

The concurrency model presented above with lightweight processes and mechanisms to communicate and monitor each other gives the developers tools to build fault-tolerant and scalable distributed systems.

In OTP, there are also common abstractions to create so-called “supervision trees”. This allows you to decompose your system into a tree structure where errors in one part of the system do not propagate to the other part but are handled by the supervisor process of a particular branch. Most of the time, a process that generated the error is restarted with its state restored and this is transparent to other parts of the system.

Case studies: Successful Elixir projects

These are the highlights of successful Elixir projects achieved by various companies in collaboration with Erlang Solutions. Each detailed story is available in the case study in the corresponding link.

Company nameKey benefits
Bleacher ReportThere is a significant reduction in code complexity, a considerable decrease in development time, and significant cost savings. Additionally, time and resources are freed up to address technical debt, and there is excellent availability of coding expertise after converting the Ruby team into Elixir experts.
TV4Migrated millions of subscribers from an external service to a user management application with zero downtime.Reduced server consumption and decreased infrastructure costs.
BET SoftwareCode complexity is significantly reduced, development time decreases, and costs are lower. Time and resources are freed to address technical debt, with strong coding expertise after converting the Ruby team to Elixir.
International Registries, Inc. (IRI)Run highly parallel processes and eliminate system bottlenecks. A distributed data architecture ensuring system availability even during data center failures. An innovative event ingress system capable of processing up to 300,000 market changes on peak days, enabling real-time event processing and live betting.

Enhancing team skills with Elixir tutorials

As the Elixir community is growing, so is the availability of learning materials. Besides our blogs and tutorials, there are online platforms for learning programming and local workshops.

Here are some of the popular platforms for learning Elixir:

PlatformDescriptionFeatures
Learn ElixirA dedicated platform for Elixir enthusiasts, offering structured courses to guide learners from basics to advanced topics.Self-paced learning modules.Interactive coding challenges.Community support and forums.
ExercismA free platform offering coding exercises across various programming languages, including Elixir. It provides practice problems and mentorship to help learners improve their coding skills.Interactive exercises with real-world scenarios.Mentorship from experienced developers.Community discussions for collaborative learning.
Educative.ioAn interactive learning platform that offers a course on functional programming using Elixir.In-browser coding environment.Hands-on exercises and quizzes.Text-based lessons with visual aids.

If you prefer hands-on experience, then these are local options for learning Elixir:

Learning typeDescription
Meetups are a great way to get inspired by developers in your area. You can check meetup.com if there is a local group of enthusiasts meeting together.Conferences like ElixirConf, ElixirConf EU, Code Beam Europe, Code Beam America organise workshops with various difficulty levels.
Conference talksMeetups are a great way to get inspired by developers in your area. You can check meetup.com if there is a local group of enthusiasts meeting together.
Local meetupsMeetups are a great way to get inspired by developers in your area. You can check out on meetup.com if there is a local group of enthusiasts meeting together.

Future-proofing your company with Elixir

Elixir is not only a language with modern syntax but also a language that keeps up with emerging trends in software development, making it an interesting choice for a tech stack. Here’s a list of a few current trends where Elixir fits:

  1. Artificial Intelligence and Machine Learning Integration – The Current boom in Large Language Models (LLMs) is continuing, and the Numerical Elixir (Nx) project provides all the tooling to incorporate ML models into your systems written in Elixir.
  2. Functional Programming Paradigm – Elixir is a functional language and has all the features that many imperative languages have been adopting over the past years, such as immutable data structures, pattern matching, higher-order functions, streams
  3. Internet of Things – Elixir’s ability to manage thousands of concurrent processes makes it an excellent choice for IoT applications that require real-time data processing and high availability. Also, there are tools like Nerves that help to build IoT platforms in Elixir.
  4. Developer Productivity – According to Stack Overflow Survey 2024, Elixir is the second most admired programming language, and the Phoenix framework is the most admired web framework. This is no surprise as they provide a smooth Developer Experience and allow programmers to focus on the most essential parts of their tasks

To conclude

Elixir is a great choice whether you’re a beginner looking for a language to learn programming, a senior developer wanting to change your tech stack to be more productive or a tech lead searching for a solution to scale up your product. With our Elixir Tutorial, we’ll bring you materials and inspiration to proceed on this journey.

If you’d like to use Elixir in your product and would like the help of our experts to introduce it into your tech stack, read more about our Elixir consulting offer.

The post Elixir Tutorials appeared first on Erlang Solutions.

by Paweł Długosz at April 03, 2025 10:23

March 29, 2025

Kaidan

Kaidan 0.12.2: Message Removal and Bubble Fixes

Kaidan 0.12.2 fixes some bugs. Have a look at the changelog for more details.

Changelog

Bugfixes:

  • Fix removing corrected message (melvo)
  • Fix showing message bubble tail only for first message of sender (melvo)

Download

Or install Kaidan for your distribution:

Packaging status

March 29, 2025 23:00

March 28, 2025

Kaidan

Kaidan 0.12.1: Voice Message and Password Change Fixes

Kaidan 0.12.1 fixes some bugs. Have a look at the changelog for more details.

Changelog

Bugfixes:

  • Do not highlight unpinned chats when pinned chat is moved (melvo)
  • Fix deleting/sending voice messages (melvo)
  • Fix crash during login (melvo)
  • Fix opening chat again after going back to chat list on narrow window (melvo)
  • Increase tool bar height to fix avatar not being recognizable (melvo)
  • Fix width of search bar above chat list to take available space while showing all buttons (melvo)
  • Fix storing changed password (melvo)
  • Fix setting custom host/port for account registration (melvo)
  • Fix crash on chat removal (fazevedo)
  • Move device switching options into account details to fix long credentials not being shown and login QR code being temporarily visible on opening dialog (melvo)
  • Allow setting new password on error to fix not being able to log in after changing password via other device (melvo)

Download

Or install Kaidan for your distribution:

Packaging status

March 28, 2025 23:00

ProcessOne

ejabberd 25.03

ejabberd 25.03

Release Highlights:

If you are upgrading from a previous version, please check the changes in SQL schemas; but there aren&apost changes in the configuration, API commands or hooks.

Other contents:

Below is a detailed breakdown of the improvements and enhancements:

Matrix Gateway with Room Support

ejabberd can bridge communications to Matrix servers since version 24.02 thanks to mod_matrix_gw, but until now only one-to-one conversations were supported.

Starting with ejabberd 25.03, now you can receive invitations to Matrix rooms and join public Matrix rooms by yourself. The Matrix bridge will be seen a multi-user chat service, as default matrix.yourdomain.net.

For example, once you have enabled the Matrix bridge, if you wish to join the room #ejabberd-matrix-bridge:matrix.org, you can use XMPP MUC protocol to enter the XMPP room: #ejabberd-matrix-bridge%matrix.org@matrix.yourdomain.net

Caveats for this release:

  1. Older room protocol version are not supported yet for this release. We only support room protocol version 9, 10 and 11 for now but are planning to add support for older rooms.
  2. One to one conversation will need to be restarted empty after server restart as the persistence is not yet implemented.
  3. matrix room members are those who kind of subscribed to the room, not necessarily online, and mod_matrix_gw sends a presence for each of them, it depends on whether the xmpp client can handle thousands of muc members.

Note that matrix.org server has also declared an XMPP service in its DNS entries. To communicate with the real Matrix server, you need to block it and add this rule in your firewall on your ejabberd instance:

iptables -A OUTPUT -d lethe.matrix.org -j REJECT

As a reminder, as encrypted payloads are different in Matrix and XMPP, Matrix payload cannot be end-to-end encrypted. In the future, it could be possible to join Matrix encrypted room, with the decryption happening on the server in the bridge, but it will not be end-to-end encrypted anymore. It would just be a convenience for those trusting their XMPP server. Please, let us know if this is an option you would like to see in the future.

Support Multiple Simultaneous Password Types

Faithful to our commitment to help gradually ramp up messaging security, we added the ability to store passwords in multiple formats per account. This feature should help with migration to newer, more secure authentication methods. Using the option auth_stored_password_types, you can specify in what formats the password will be stored in the database. And the stored passwords will be updated each time user changes the password or when the user&aposs client provides the password in a new format using SASL Upgrade Tasks XEP specification.

This option takes a list of values, currently recognized ones are plain, scram_sha1, scram_sha256, scram_sha512. When this options is set, it overrides old options that allowed to specify password storage - auth_scream_hash and auth_password_format.

Update SQL Schema

This release requires SQL database schema update to allow storage of multiple passwords per user. This task can be performed automatically by ejabberd, if your config has enabled update_sql_schema toplevel option.

If you prefer to perform the SQL schema update manually yourself, check the corresponding instructions, depending if your config has enabled new_sql_schema:

  • MySQL default schema:
ALTER TABLE users ADD COLUMN type smallint NOT NULL DEFAULT 0;
ALTER TABLE users ALTER COLUMN type DROP DEFAULT;
ALTER TABLE users DROP PRIMARY KEY, ADD PRIMARY KEY (username(191), type);
  • MySQL new schema:
ALTER TABLE users ADD COLUMN type smallint NOT NULL DEFAULT 0;
ALTER TABLE users ALTER COLUMN type DROP DEFAULT;
ALTER TABLE users DROP PRIMARY KEY, ADD PRIMARY KEY (server_host(191), username(191), type);
  • PostgreSQL default schema:
ALTER TABLE users ADD COLUMN "type" smallint NOT NULL DEFAULT 0;
ALTER TABLE users ALTER COLUMN type DROP DEFAULT;
ALTER TABLE users DROP CONSTRAINT users_pkey, ADD PRIMARY KEY (username, type);
  • PostgreSQL new schema:
ALTER TABLE users ADD COLUMN "type" smallint NOT NULL DEFAULT 0;
ALTER TABLE users ALTER COLUMN type DROP DEFAULT;
ALTER TABLE users DROP CONSTRAINT users_pkey, ADD PRIMARY KEY (server_host, username, type);
  • SQLite default schema:
ALTER TABLE users ADD COLUMN type smallint NOT NULL DEFAULT 0;
CREATE TABLE new_users (
    username text NOT NULL,
    type smallint NOT NULL,
    password text NOT NULL,
    serverkey text NOT NULL DEFAULT &apos&apos,
    salt text NOT NULL DEFAULT &apos&apos,
    iterationcount integer NOT NULL DEFAULT 0,
    created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (username, type)
);
INSERT INTO new_users SELECT * FROM users;
DROP TABLE users;
ALTER TABLE new_users RENAME TO users;
  • SQLite new schema:
ALTER TABLE users ADD COLUMN type smallint NOT NULL DEFAULT 0;
CREATE TABLE new_users (
    username text NOT NULL,
    server_host text NOT NULL,
    type smallint NOT NULL,
    password text NOT NULL,
    serverkey text NOT NULL DEFAULT &apos&apos,
    salt text NOT NULL DEFAULT &apos&apos,
    iterationcount integer NOT NULL DEFAULT 0,
    created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (server_host, username, type)
);
INSERT INTO new_users SELECT * FROM users;
DROP TABLE users;
ALTER TABLE new_users RENAME TO users;

New mod_adhoc_api module

You may remember this paragraph from the ejabberd 24.06 release notes:

ejabberd already has around 200 commands to perform many administrative tasks, both to get information about the server and its status, and also to perform operations with side-effects. Those commands have its input and output parameters clearly described, and also documented.

Almost a year ago, ejabberd WebAdmin got support to execute all those 200 API commands... and now your XMPP client can execute them too!

The new mod_adhoc_api ejabberd module allows to execute all the ejabberd API commands using a XMPP client that supports XEP-0050 Ad-Hoc Commands and XEP-0030 Service Discovery.

Simply add this module to modules, setup api_permissions to grant some account permission to execute some command, or tags of commands, or all commands. Reload the ejabberd configuration and login with your client to that account.

Example configuration:

acl:
  admin:
    user: jan@localhost

api_permissions:
  "adhoc commands":
    from: mod_adhoc_api
    who: admin
    what:
      - "[tag:roster]"
      - "[tag:session]"
      - stats
      - status

modules:
  mod_adhoc_api:
    default_version: 2

Now you can execute the same commands in the command line, using ReST, in the WebAdmin, and in your XMPP client!

This feature has been tested with Gajim, Psi, Psi+ and Tkabber. Conversejs allows to list and execute the commands, but doesn&apost show the result to the user.

Macros and Keyword improvements

Some options in ejabberd supported the possibility to use hard-coded keywords. For example, many modules like mod_vcard could used HOST in their hosts option. Other example is the captcha_cmd toplevel option: it could use VERSION and SEMVER keywords. All this was implemented for each individual option.

Now those keywords are predefined and can be used by any option, and this is implemented in ejabberd core, no need to implement the keyword substitution in each option. The predefined keywords are: HOST, HOME, VERSION and SEMVER.

For example, this configuration is now possible without requiring any specific implementation in the option source code:

ext_api_url: "http://example.org/@VERSION@/api"

Additionally, now you can define your own keywords, similarly to how macros are defined:

define_keyword:
  SCRIPT: "captcha.sh"

captcha_cmd: "tools/@SCRIPT@"

And finally, now macros can be used inside string options, similarly to how keywords can be used:

define_macro:
  SCRIPT: "captcha.sh"

captcha_cmd: "tools/@SCRIPT@"

In summary, now macros and keywords can be defined and used very similarly, so you may be wondering what are their differences. That is explained in detail in the new section Macros and Keywords:

  • Macros are implemented by the yconf library: macros cannot be defined inside host_config.

  • Keywords are implemented by ejabberd itself: keywords can be defined inside host_config but only for usage in module options. And cannot be used in those toplevel options: hosts, loglevel, version.

ejabberdctl: New option CTL_OVER_HTTP

The ejabberdctl script is useful not only to start and stop ejabberd, it can also execute the ~200 ejabberd API commands inside the running ejabberd node. For this, the script starts another erlang virtual machine and connects it to the already existing one that is running ejabberd.

This connection method is acceptable for performing a few administrative tasks (reload configuration, register an account, etc). However, ejabberdctl is noticeably slow for performing multiple calls, for example to register 1000 accounts. In that case, it is preferable to use other API frontend like mod_http_api or ejabberd_xmlrpc.

And now ejabberdctl can do exactly this! ejabberdctl can be configured to use an HTTP connection to execute the command, which is way faster than starting an erlang node, around 20 times faster.

To enable this feature, first configure in ejabberd.yml:

listen:
  -
    port: "unix:sockets/ctl_over_http.sock"
    module: ejabberd_http
    unix_socket:
      mode: &apos0600&apos
    request_handlers:
      /ctl: ejabberd_ctl

Then enable the CTL_OVER_HTTP option in ejabberdctl.cfg:

CTL_OVER_HTTP=sockets/ctl_over_http.sock

Let&aposs register 100 accounts using the standard method and later using CTL_OVER_HTTP:

$ time for (( i=100 ; i ; i=i-1 )) ; do ejabberdctl register user-standard-$i localhost pass; done
...
real    0m43,929s
user    0m41,878s
sys     0m10,558s

$ time for (( i=100 ; i  ; i=i-1 )) ; do CTL_OVER_HTTP=sockets/ctl_over_http.sock ejabberdctl register user-http-$i localhost pass; done
...
real    0m2,144s
user    0m1,377s
sys     0m0,566s

This feature is enabled by default in the ejabberd container image.

mod_configure: New option access

mod_configure always had support to configure what accounts can access its features: using the configure access rule. The name of that access rule was hard-coded. Now, thanks to the new access option, that can be configured.

Container images: Reduce friction, use macros, WebAdmin port

Several improvements are added in the ejabberd and ecs container images to allow easier migration from one to the other. This also allows to use the same documentation file for both container images, as now there are very few usability differences between both images. Also, a new comparison table in that documentation describes all the differences between both images. The improvements are:

  • Adds support for paths from ecs into ejabberd container image, and viceversa: /opt/ linked to /home/ and /usr/local/bin/ linked to /opt/ejabberd/bin/
  • Include the ejabberdapi binary also in the ejabberd container image, as does ecs
  • Copy captcha scripts to immutable path /usr/local/bin/ for easy calling, and it&aposs included in $PATH
  • Copy sql files to /opt/ejabberd/database/sql/
  • Copy sql also to /opt/ejabberd/database/ for backwards compatibility with ecs
  • Link path to Mnesia spool dir for backwards compatibility
  • CONTAINER.md now documents both images, as there are few differences. Also includes a comparison table

Macros are used in the default ejabberd.yml configuration files to define host, admin account and port numbers. This way you can overwrite any of them at starttime using environment variables:

     env:
     - name: PORT_HTTP_TLS
       value: 5444

If you use the podman-desktop or docker-desktop applications, you may have noticed they show a button named "Open Browser". When you click that button, it opens a web browser with / URL and the lowest exposed port number. Now the default ejabberd.yml configuration file listens in port number 1880, the lowest of all, so the "Open Browser" button will open directly the ejabberd WebAdmin page.

ejabberd container image: admin account

In the ejabberd container image, you can grant admin rights to an account using the EJABBERD_MACRO_ADMIN environment variable. Additionally, if you set the REGISTER_ADMIN_PASSWORD environment variable, that account is automatically registered.

Example kubernetes yaml file in podman:

     env:
     - name: EJABBERD_MACRO_ADMIN
       value: administrator@example.org
     - name: REGISTER_ADMIN_PASSWORD
       value: somePass0rd

When those environment variables are not set, admin rights are granted to a random account name in the default ejabberd.yml.

Alternatively, this can be done with the existing CTL_ON_CREATE variable, and then you would need to modify ejabberd.yml accordingly:

     env:
     - name: CTL_ON_CREATE
       value: register administrator example.org somePass0rd

Unix Domain Socket: Relative path

There are several minor improvements in the Unix Domain Socket support, the most notable being support for socket relative path: if the port option is set to "unix:directory/filename" without absolute path, then the directory and file are created in the Mnesia spool directory.

Privileged Entity Bugfixes

Two bugs related to XEP-0356: Privileged Entity have been solved:

Don&apost rewrite "self-addressed" privileged IQs as results

process_privilege_iq is meant to rewrite the result of a privileged IQ into the forwarded form required by XEP-0356 so it can be routed back to the original privileged requester. It checks whether the impersonated JID (ReplacedJid) of the original request matches the recipient of the IQ being processed to determine if this is a response to a privileged IQ (assuming it has privileged-IQ metadata attached).

Unfortunately, it doesn&apost check the packet type, and this check will also match a privileged-IQ request that is being sent to the same user that&aposs being impersonated. This results in the request itself being rewritten and forwarded back to the sending component, instead of being processed and having the result send back.

Instead, just check for IQ results (either a regular result or an error), and as long as it is marked as being a response to a privileged-IQ, always rewrite it and forward it to the sending component. There&aposs no circumstance under which we shouldn&apost forward a privileged-IQ response, so we don&apost need to be tricky about checking whether impersonated-user and recipient match.

Accept non-privileged IQs from privileged components

mod_privilege current drops any non-privileged IQ received from a component with an error about it not being properly wrapped. While this might represent a mistake on the part of the component, it means that well- behaved components can no longer send non-privileged IQs (something they normally can do if mod_privilege isn&apost enabled).

Since mod_privilege is intended to grant additional permissions, and not remove existing ones, route non-privileged IQs received from the component normally.

This also removes the special-case for roster-query IQ stanzas, since those are also non-privileged and will be routed along with any other non-privileged IQ packet. This mirrors the privileged-IQ/everything-else structure of the XEP, which defined the handling of privileged IQ stanzas and leaves all other IQ stanzas as defined in their own specs.

To make this clearer, the predicate function now returns distinct results indicating privileged IQs, non-privileged IQs, and error conditions, rather than treating non-privilege IQs as an error that gets handled by routing the packet normally.

mod_muc_occupantid: Enable in the default configuration

mod_muc_occupantid was added to the list of modules enabled in the sample configuration file ejabberd.yml.example.

It&aposs not necessarily obvious that it&aposs required for using certain modern features in group chat, and there&aposs no downside in activating this module.

mod_http_api returns sorted list elements

When mod_http_api returns a list of elements, now those elements are sorted alphabetically. If it is a list of tuples, the tuples are sorted alphabetically by the first element in that tuple.

Notice that the new module mod_adhoc_api uses internally mod_http_api to format the API command arguments and result, this means that mod_adhoc_api benefits from this feature too.

create_room_with_opts API command separators

One of the arguments accepted by the create_room_with_opts API command is a list of room options, expressed as tuples of option name and option value. And some room option values are also list of tuples! This is the case of affiliations and subscribers.

That is not a problem for API frontends that accept structured arguments like mod_http_api and ejabberd_xmlrpc. But this is a problem in ejabberdctl, mod_adhoc_api and WebAdmin, because they don&apost use structured arguments, and instead separate list elements with , and tuple elements with :. In that case, a list of tuples of list of tuples cannot be parsed correctly if all them use the same separators.

Solution: when using the create_room_with_opts command to set affiliations and subscribers options:

  • list elements were separated with , and now should be with ;
  • tuple elements were separated with : and now should be with =

All the previous separators are still supported for backwards compatibility, but please use the new recommended separators, specially if using ejabberdctl, mod_adhoc_api and WebAdmin.

Let&aposs see side by side the old and the new recommended syntax:

affiliations:owner:user1@localhost,member:user2@localhost
affiliations:owner=user1@localhost;member=user2@localhost

In a practical example, instead of this (which didn&apost work at all):

ejabberdctl \
  create_room_with_opts \
  room_old_separators \
  conference.localhost \
  localhost \
  "persistent:true,affiliations:owner:user1@localhost,member:user2@localhost"

please use:

ejabberdctl \
  create_room_with_opts \
  room_new_separators \
  conference.localhost \
  localhost \
  "persistent:true,affiliations:owner=user1@localhost;member=user2@localhost"

Notice that both the old and new separators are supported by create_room_with_opts. For example, let&aposs use curl to query mod_http_api:

curl -k -X POST -H "Content-type: application/json" \
     "http://localhost:5280/api/create_room_with_opts" \
     -d &apos{"name": "room_old_separators",
          "service": "conference.localhost",
          "host": "localhost",
          "options": [
           {"name": "persistent",
            "value": "true"},
           {"name": "affiliations",
            "value": "owner:user1@localhost,member:user2@localhost"}
          ]
         }&apos

curl -k -X POST -H "Content-type: application/json" \
     "http://localhost:5280/api/create_room_with_opts" \
     -d &apos{"name": "room_new_separators",
          "service": "conference.localhost",
          "host": "localhost",
          "options": [
           {"name": "persistent",
            "value": "true"},
           {"name": "affiliations",
            "value": "owner=user1@localhost;member=user2@localhost"}
          ]
         }&apos

New API commands to change Mnesia table storage

There are two new API commands: mnesia_list_tables and mnesia_table_change_storage.

In fact those commands were already implemented since ejabberd 24.06, but they were tagged as internal as they were only used by WebAdmin. Now they are available for any API frontend, including mod_adhoc_api.

Erlang/OTP and Elixir versions support

Let&aposs review the supported Erlang/OTP versions:

  • Erlang/OTP 20.0 up to 24.3 are discouraged: ejabberd 25.03 is the last ejabberd release that fully supports those old erlang versions. If you are still using any of them, please upgrade it before the next ejabberd release.

  • Erlang/OTP 25.0 up to 27.3 are the recommended versions. For example Erlang/OTP 27.3 is used in the ejabberd binary installers and ejabberd container image.

  • Erlang/OTP 28.0-rc2 is mostly supported, but not yet recommended for production deployments.

Regarding Elixir supported versions:

  • Elixir 1.10.3 up to 1.12.3 are discouraged: ejabberd compilation is not tested with those old Elixir versions.

  • Elixir 1.13.4 up to 1.18.3 are the recommended versions; for instance Elixir 1.18.3 is used in the ejabberd binary installers and container images.

Acknowledgments

We would like to thank the contributions to the source code, documentation, and translation provided for this release by:

And also to all the people contributing in the ejabberd chatroom, issue tracker...

Improvements in ejabberd Business Edition

Customers of the ejabberd Business Edition, in addition to all those improvements and bugfixes, also get the floowing fixes

  • Fix mod_unread with s2s messages
  • Fix logic detecting duplicate pushes to not trigger pushes on other backends
  • Fix issue with connection to Apple push servers for APNS delivery
  • Fix server_info commands when a cluster node is not available

ChangeLog

This is a more detailed list of changes in this ejabberd release:

Commands API

  • ejabberdctl: New option CTL_OVER_HTTP (#4340)
  • ejabberd_web_admin: Support commands with tuple arguments
  • mod_adhoc_api: New module to execute API Commands using Ad-Hoc Commands (#4357)
  • mod_http_api: Sort list elements in a command result
  • Show warning when registering command with an existing name
  • Fix commands unregistration
  • change_room_option: Add forgotten support to set enable_hats room option
  • change_room_option: Verify room option value before setting it (#4337)
  • create_room_with_opts: Recommend using ; and = separators
  • list_cluster_detailed: Fix crash when a node is down
  • mnesia_list_tables: Allow using this internal command
  • mnesia_table_change_storage: Allow using this internal command
  • status: Separate command result with newline
  • update_sql: Fix updating tables created by ejabberd internally
  • update_sql: Fix MySQL support

Configuration

  • acl: Fix bug matching the acl shared_group: NAME
  • define_keyword: New option to define keywords (#4350)
  • define_macro: Add option to globals() because it&aposs useless inside host_config
  • ejabberd.yml.example: Enable mod_muc_occupantid by default
  • Add support to use keywords in toplevel, listener and modules
  • Show warning also when deprecated listener option is set as disabled (#4345)

Container

  • Bump versions to Erlang/OTP 27.3 and Elixir 1.18.3
  • Add ERL_FLAGS to compile elixir on qemu cross-platform
  • Copy files to stable path, add ecs backwards compatibility
  • Fix warning about relative workdir
  • Improve entrypoint script: register account, or set random
  • Link path to Mnesia spool dir for backwards compatibility
  • Place sockets/ outside database/
  • Use again direct METHOD, qemu got fixed (#4280)
  • ejabberd.yml.example: Copy main example configuration file
  • ejabberd.yml.example: Define and use macros in the default configuration file
  • ejabberd.yml.example: Enable CTL_OVER_HTTP by default
  • ejabberd.yml.example: Listen for webadmin in a port number lower than any other
  • ejabberdapi: Compile during build
  • CONTAINER.md: Include documentation for ecs container image

Core and Modules

  • ejabberd_auth: Add support for auth_stored_password_types
  • ejabberd_router: Don&apost rewrite "self-addressed" privileged IQs as results (#4348)
  • misc: Fix json version of json_encode_with_kv_list for nested kv lists (#4338)
  • OAuth: Fix crashes when oauth is feed with invalid jid (#4355)
  • PubSub: Bubble up db errors in nodetree_tree_sql:set_node
  • mod_configure: Add option access to let configure the access name
  • mod_mix_pam: Remove Channels roster group of mix channels (#4297)
  • mod_muc: Document MUC room option vcard_xupdate
  • mod_privilege: Accept non-privileged IQs from privileged components (#4341)
  • mod_private: Improve exception handling
  • mod_private: Don&apost warn on conversion errors
  • mod_private: Handle invalid PEP-native bookmarks
  • mod_private: Don&apost crash on invalid bookmarks
  • mod_s2s_bidi: Stop processing other handlers in s2s_in_handle_info (#4344)
  • mod_s2s_bidi: Fix issue with wrong namespace

Dependencies

  • ex_doc: Bump to 0.37.2
  • stringprep: Bump to 1.0.31
  • provider_asn1: Bump to 0.4.1
  • xmpp Bump to bring fix for ssdp hash calculation
  • xmpp Bump to get support for webchat_url (#3041)
  • xmpp Bump to get XEP-0317 Hats namespaces version 0.2.0
  • xmpp Bump to bring SSDP to XEP version 0.4
  • yconf Bump to support macro inside string

Development and Testing

  • mix.exs: Keep debug info when building dev release
  • mix.exs: The ex_doc dependency is only relevant for the edoc Mix environment
  • ext_mod: add $libdir/include to include path
  • ext_mod: fix greedy include path (#4359)
  • gen_mod: Support registering commands and hook_subscribe in start/2 result
  • c2s_handle_bind: New event in ejabberd_c2s (#4356)
  • muc_disco_info_extras: New event mod_muc_room useful for mod_muc_webchat_url (#3041)
  • VSCode: Fix compiling support
  • Add tests for config features define_macro and define_keyword
  • Allow test to run using ct_run
  • Fixes to handle re-running test after update_sql
  • Uninstall mod_example when the tests has finished

Documentation

  • Add XEPs that are indirectly supported and required by XEP-0479
  • Document that XEP-0474 0.4.0 was recently upgraded
  • Don&apost use backtick quotes for ejabberd name
  • Fix values allowed in db_type of mod_auth_fast documentation
  • Reword explanation about ACL names and definitions
  • Update moved or broken URLs in documentation

Installers

  • Bump Erlang/OTP 27.3 and Elixir 1.18.3
  • Bump OpenSSL 3.4.1
  • Bump crosstool-NG 1.27.0
  • Fix building Termcap and Linux-PAM

Matrix Gateway

  • Preserve XMPP message IDs in Matrix rooms
  • Better Matrix room topic and room roles to MUC conversion, support room aliases in invites
  • Add muc#user element to presences and an initial empty subject
  • Fix gen_iq_handler:remove_iq_handler call
  • Properly handle IQ requests
  • Support Matrix room aliases
  • Fix handling of 3PI events

Unix Domain Socket

  • Add support for socket relative path
  • Use /tmp for temporary socket, as path is restricted to 107 chars
  • Handle unix socket when logging remote client
  • When stopping listener, delete Unix Domain Socket file
  • get_auto_url option: Don&apost build auto URL if port is unix domain socket (#4345)

Full Changelog

https://github.com/processone/ejabberd/compare/24.12...25.03

ejabberd 25.03 download & feedback

As usual, the release is tagged in the Git source code repository on GitHub.

The source package and installers are available in ejabberd Downloads page. To check the *.asc signature files, see How to verify ProcessOne downloads integrity.

For convenience, there are alternative download locations like the ejabberd DEB/RPM Packages Repository and the GitHub Release / Tags.

The ecs container image is available in docker.io/ejabberd/ecs and ghcr.io/processone/ecs. The alternative ejabberd container image is available in ghcr.io/processone/ejabberd.

If you consider that you&aposve found a bug, please search or fill a bug report on GitHub Issues.

by Jérôme Sautret at March 28, 2025 17:27

Ignite Realtime Blog

It’s time for real interoperability. Let’s make it happen!

When I explain to others what I do for a living, I often ask why it is that we are not surprised that one can use a Gmail account to send an email to someone who uses an Outlook account, yet many people fully accept that you can’t send a message to someone using WhatsApp from a Telegram account. We’re not surprised that we can use our phone to set up a call with someone who uses a different brand of phone (or is subscribed to a different provider), yet, for instant messaging, we find ourselves in a world of walled gardens.

Walled gardens refer to ecosystems where companies control access to their platforms and restrict users’ ability to freely interact with other services, creating barriers that prevent open communication and fair competition.

Recognizing this, legislation is slowly being put in place to improve things. The Digital Markets Act (DMA) is a regulatory framework established aimed at ensuring fair competition and improving the functioning of the digital economy. One of its primary objectives is to dismantle these walled gardens and promote messaging interoperability. The DMA seeks to break down barriers and ensure that users have more freedom to engage with different platforms and services, while also enabling interoperability between messaging services.

Meta (of WhatsApp and Facebook fame) is designated as a “gatekeeper” under the DMA. This means that Meta holds a dominant position in the market, controlling key access points that can potentially limit competition or consumer choice. The act outlines various obligations that Meta must comply with to ensure a fairer and more open digital environment.

The XMPP Standards Foundation is now publishing an Open Letter to Meta, to advocate for the adoption of XMPP for messaging interoperability. It argues that Meta’s proposal falls short: Meta’s current approach to interoperability, which relies on restrictive NDAs, proprietary APIs, and centralized control, is not true interoperability.

The XSF argues that Meta should adopt XMPP (eXtensible Messaging and Presence Protocol), a proven, open standard that allows for true federation, decentralization, enhanced privacy, and scalability. XMPP enables seamless communication between different services, akin to email or phone networks. Meta has previously utilized XMPP for WhatsApp and Messenger and has embraced federation for other services, showing that adoption and implementation are not only achievable, but has already been proven to work.

The XSF urges Meta to adopt XMPP for messaging interoperability to comply with the DMA and build a competitive, open messaging ecosystem. The XSF is ready to collaborate and evolve the protocol as needed.

The Ignite Realtime community is based on the strength and flexibility offered by XMPP. Projects like Openfire, Smack, Pade and Spark are direct implementations of the XMPP protocol. We have firsthand witnessed the flexibility, reliability and maturity of the protocol, and have been successfully applying it for years, if not decades. We should therefore fully endorse the XSF’s call to action!

It is time for real interoperability. Let’s make it happen!

You can find the Open Letter of the XSF here: XMPP | Open Letter to Meta: Support True Messaging Interoperability with XMPP

A accompanying technical briefing is also published: XMPP | Detailed technical briefing: The Case for XMPP – Why Meta Must Embrace True Messaging Interoperability

For other release announcements and news follow us on Mastodon or X

1 post - 1 participant

Read full topic

by guus at March 28, 2025 15:41

ProcessOne

Supporting XMPP Standard Foundation's open letter to Meta for true interop

Supporting XMPP Standard Foundation's open letter to Meta for true interop

The XMPP Standards Foundation (XSF) has published an open letter to Meta, asking them to support true messaging interoperability using the XMPP protocol.

Meta had previously integrated this protocol, and WhatsApp was actually built on an XMPP-based server, and Meta has previously supported XMPP in Facebook Messenger, as explained in XSF&aposs technical briefing:

A Call to Meta: Build Your Interoperability Stack on XMPP

We at the XMPP Standards Foundation (XSF) urge Meta to build its interoperability framework on top of XMPP federation.

If Threads can implement the Fediverse protocol, there is no reason why Meta cannot do the same with XMPP for Facebook Messenger and WhatsApp—especially since WhatsApp itself was originally built on XMPP.

Why This Matters

We support this initiative as it represents the best approach for genuine interoperability. The European Digital Markets Act (DMA) is specifically designed to break down walled gardens and enforce messaging interoperability across platforms.

XMPP has played a crucial role in shaping the modern messaging landscape, and its success demonstrates that true interoperability is achievable across different platforms and services. It remains the most viable and battle-tested solution to meet interoperability requirements.

As a free and open standard for building and deploying instant messaging systems, XMPP represents the ideal foundation for true messaging interoperability.

Take Action to #FederateTheWorld

Federation is the way to go! Learn more by reading the announcement on the XSF website, where they provide both the open letter and a detailed technical briefing explaining the reasoning behind this call to action.

The XSF, as well as ProcessOne as a long time supporter, is ready to collaborate with Meta and continue to evolve the protocol to meet modern messaging needs.

by Mickaël Rémond at March 28, 2025 14:25

Mathieu Pasquet

Poezio 0.15 / 0.15.1

About three years since the last version, poezio 0.15 (and 0.15.1 to address a small packaging mishap, version numbers are cheap) was released yesterday!

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.

Features

Not a lot this time around… Maybe next time?

  • A new moderate plugin (for XEP-0425 moderation).
  • Better self-ping (through the use of the slixmpp now builtin XEP-0410 plugin).
  • Use the system CA store by default.
  • Add a Ctrl-↑ shortcut to run /correct on the last message.
  • Poezio benefits from the recent slixmpp improvements, which means it can now transparently use Direct TLS as well as StartTLS.

Fixes

  • Duplicated first message in conversation/private tab.
  • The many "clone" users in a room roster when on a spotty connection.
  • Python 3.13 and 3.14 compatibility (plenty of deprecations and removals).
  • Plenty of type checking mistakes and minor bugs spotted by mypy and pylint.

Removals

  • Only python 3.11 and up is supported (was: 3.7).
  • The OTR plugin has been removed.
  • The launch/update.sh have been heavily simplified to use the uv tool instead of custom logic. It will be updated in the future to be able to run on pipx too, as uv is not available on some platforms.

by mathieui at March 28, 2025 07:32

March 27, 2025

Erlang Solutions

My Journey from Ruby to Elixir: Lessons from a Developer

Why I Looked Beyond Ruby

For years, Ruby was my go-to language for building everything from small prototypes to full-fledged production apps. I fell in love with its elegance and expressiveness and how Ruby on Rails could turn an idea into a working web app in record time. The community—with its focus on kindness and collaboration—only deepened my appreciation. In short, Ruby felt like home.

But as my projects grew in complexity, I started running into bottlenecks. I had apps requiring real-time features, massive concurrency, and high availability. Scaling them with Ruby often meant juggling multiple processes, external services, or creative threading approaches—all of which worked but never felt truly seamless. That’s when I stumbled upon Elixir.

At first glance, Elixir’s syntax reminded me of Ruby. It looked approachable and developer-friendly. But beneath the surface lies a fundamentally different philosophy, heavily influenced by Erlang’s functional model and the concurrency power of the BEAM. Moving from Ruby’s object-oriented approach to Elixir’s functional core was eye-opening. Here’s how I made that transition and why I think it’s worth considering if you’re a fellow Rubyist.

The Mindset Shift: From Objects to Functions

Life Before: Classes and Objects

In Ruby, I approached problems by modeling them as classes, bundling data and behavior together. It was second nature to create an @name instance variable in an initializer, mutate it, and rely on inheritance or modules to share behavior. This style allowed me to write expressive code, but it also hid state changes behind class boundaries.

A New Paradigm in Elixir

Elixir flips that script. Data is immutable, and functions are the stars of the show. Instead of objects, I have modules that hold pure functions. Instead of inheritance, I rely on composition and pattern matching. This required me to unlearn some habits.

  • No more hidden state: Every function receives data as input and returns a new copy of that data, so you always know where transformations happen.

No more deep class hierarchies: In Elixir, code sharing happens via modules and function imports rather than extending base classes.

Example: Refactoring a Class into a Module

Ruby

class Greeter
  def initialize(name)
    @name = name
  end

  def greet
    "Hello, #{@name}!"
  end
end

greeter = Greeter.new("Ruby")
puts greeter.greet  # => "Hello, Ruby!"

Elixir

defmodule Greeter do

  def greet(name), do: "Hello, #{name}!"

end
IO.puts Greeter.greet("Elixir")  # => "Hello, Elixir!"

At first, I missed the idea of storing state inside an object, but soon realized how clean and predictable code can be when data and functions are separated. Immutability drastically cut down on side effects, which in turn cut down on surprises.

Concurrency: Learning to Trust Processes

Ruby’s approach

Ruby concurrency typically means spinning up multiple processes or using multi-threading for IO-bound tasks. If you need to queue background jobs, gems like Sidekiq step in. Sidekiq runs in its own OS processes, separate from the main web server, and these processes can run on multiple cores for true parallelism. This approach is straightforward but often demands more memory and additional infrastructure for scaling.

On the plus side, Ruby can handle many simultaneous web requests if they’re primarily IO-bound (such as database queries). Even with the Global Interpreter Lock (GIL) limiting the parallel execution of pure Ruby code, IO tasks can still interleave, allowing a single OS process to serve multiple requests concurrently.

Elixir and the BEAM

Elixir, on the other hand, was built for concurrency from the ground up, thanks to the BEAM virtual machine. It uses lightweight processes (not OS processes or threads) that are cheap to create and easy to isolate. These processes don’t share memory but communicate via message passing—meaning a crash in one process won’t cascade.

Example: Background Jobs

Ruby (Sidekiq)

class UserSyncJob
  include Sidekiq::Worker

  # This job fetches user data from an external API
  # and updates the local database.
  def perform(user_id)
    begin
      # 1. Fetch data from external service
      external_data = ExternalApi.get_user_data(user_id)

      # 2. Update local DB (pseudo-code)
      user = User.find(user_id)
      user.update(
        name: external_data[:name],
        email: external_data[:email]
      )

      puts "Successfully synced user #{user_id}"
    rescue => e
      # If something goes wrong, Sidekiq can retry
      # automatically, or we can log the error.
      puts "Error syncing user #{user_id}: #{e.message}"
    end
  end
end

# Trigger the job asynchronously:
UserSyncJob.perform_async(42)

Elixir (Oban)

Although GenServer is often used to showcase Elixir’s concurrency model, a more accurate comparison to Sidekiq would be Oban – a background job processing library.

defmodule MyApp.Workers.UserSyncJob do
  use Oban.Worker, queue: :default

  @impl Oban.Worker
  def perform(%{args: %{"user_id" => user_id}}) do
    with {:ok, external_data} <- ExternalApi.get_user_data(user_id),
         %User{} = user <- MyApp.Repo.get(User, user_id) do
      user
      |> User.changeset(%{
        name: external_data.name,
        email: external_data.email
      })
      |> MyApp.Repo.update!()

      IO.puts("Successfully synced user #{user_id}")
    else
      error -> IO.puts("Error syncing user #{user_id}: #{inspect(error)}")
    end

    :ok
  end
end

# Enqueue the job asynchronously:
MyApp.Workers.UserSyncJob.new(%{"user_id" => 42})
|> Oban.insert()


With Oban, jobs are persistent, retried automatically on failure, and can survive restarts – just like Sidekiq. It leverages Elixir’s process model but gives you the robustness of a mature job queueing system. Since it stores jobs in PostgreSQL, you get full visibility into job states and histories without adding extra infrastructure. Both libraries offer paid tiers – Sidekiq Pro , Oban Pro.

Here are some notable features offered in the Pro versions of Sidekiq and Oban:

Sidekiq Pro:

  1. Batches and Callbacks: Enables grouping jobs into sets that can be tracked collectively programmatically or within the Sidekiq Web interface, with the ability to execute callbacks once all jobs in a batch are complete.
  2. Enhanced Reliability: Utilizes Redis’s RPOPLPUSH command to ensure that jobs are not lost if a process crashes or is terminated unexpectedly. Additionally, the Sidekiq Pro client can withstand transient Redis outages or timeouts by enqueueing jobs locally upon error and attempting delivery once connectivity is restored. ​
  3. Queue Pausing and Scheduling: Allows for pausing queues (e.g., processing a queue only during business hours) and expiring unprocessed jobs after a specified deadline, providing greater control over job processing times.

Oban Pro:

  1. Workflows: Enables composing jobs with arbitrary dependencies, allowing for sequential, fan-out, and fan-in execution patterns to model complex job relationships.
  2. Global Concurrency and Rate Limiting: Provides the ability to limit the number of concurrent jobs running across all nodes (global concurrency) and to restrict the number of jobs executed within a specific time window (rate limiting).
  3. Dynamic Cron: Offers cron configuration scheduling before boot or during runtime, globally, with scheduling guarantees and per-entry timezone overrides. It’s an ideal solution for applications that can’t miss a cron job or must dynamically start and manage scheduled jobs at runtime.

Their open-source cores, however, already cover the most common background job needs and are well-suited for many production applications.

Debugging and Fault Tolerance: A New Perspective

Catching Exceptions in Ruby

Error handling in Ruby typically involves begin/rescue blocks. If a critical background job crashes, I might rely on Sidekiq’s retry logic or external monitoring. It worked, but I always worried about a missed exception bringing down crucial parts of the app.

Supervision Trees in Elixir

Elixir uses a concept called a supervision tree, inherited from Erlang’s OTP. Supervisors watch over processes, restarting them automatically if they crash. At first, I found it odd to let a process crash on purpose instead of rescuing the error. But once I saw how quickly the supervisor restarted a failed process, I was hooked.

defmodule Worker do
  use GenServer

  def start_link(_) do
	GenServer.start_link(__MODULE__, %{}, name: __MODULE__)
  end

  def init(_), do: {:ok, %{}}

  def handle_call(:risky, _from, state) do
    raise "Something went wrong"
    {:reply, :ok, state}
  end
end

defmodule SupervisorTree do
  use Supervisor

  def start_link(_) do
    Supervisor.start_link(__MODULE__, :ok, name: __MODULE__)
  end

  def init(:ok) do
    children = [
      {Worker, []}
    ]
    Supervisor.init(children, strategy: :one_for_one)
  end
end

Now, if Worker crashes, the supervisor restarts it automatically. No manual intervention, no separate monitoring service, and no global meltdown.

LiveView: A Game-Changer for Web Development

Why I Loved Rails

Rails made it trivial to spin up CRUD apps, handle migrations, and integrate with robust testing tools like RSpec. But building real-time interactions (like chat or real-time dashboards) could be tricky without relying heavily on JavaScript frameworks or ActionCable.

Phoenix + LiveView

Elixir’s Phoenix framework parallels Rails in many ways: fast bootstrapping, a clear folder structure, and strong conventions. But Phoenix Channels and LiveView push it even further. With LiveView, I can build highly interactive, real-time features that update the DOM via websockets—all without a dedicated front-end framework.


Elixir (Phoenix LiveView)

defmodule ChatLive do
  use Phoenix.LiveView

  def mount(_params, _session, socket) do
    {:ok, assign(socket, :messages, [])}
  end

  def handle_event("send", %{"message" => msg}, socket) do
    {:noreply, update(socket, :messages, fn msgs -> msgs ++ [msg] end)}
  end

  def render(assigns) do
    ~H"""
    <h1>Chat</h1>
    <ul>
      <%= for msg <- @messages do %>
        <li><%= msg %></li>
      <% end %>
    </ul>

    <form phx-submit="send">
      <input type="text" name="message" placeholder="Type something"/>
      <button type="submit">Send</button>
    </form>
    """
  end
end

This simple LiveView code handles real-time chat updates directly from the server, minimising the JavaScript I need to write. The reactive UI is all done through server-rendered updates.

My Takeaways

Embracing Immutability

At first, it was tough to break free from the habit of mutating data in place. But once I got comfortable returning new data structures, my code became far more predictable. I stopped chasing side effects and race conditions.

Let It Crash

Ruby taught me to rescue and recover from every possible error. Elixir taught me to trust the supervisor process. This “let it crash” philosophy took some getting used to, but it simplifies error handling significantly.

Less JavaScript, More Productivity

LiveView drastically cut down my front-end overhead. I don’t need a full client framework for real-time updates. Seeing how quickly I could build a proof-of-concept live chat convinced me that Elixir was onto something big.

Still Love Ruby

None of this means I dislike Ruby. I still think Rails is fantastic for many use cases, especially when you need to prototype something quickly or build a classic CRUD app. Ruby fosters a developer-friendly environment that many languages can only aspire to. I simply reached a point where concurrency and fault tolerance became a top priority—and that’s where Elixir really shines.

Final Advice for Rubyists Curious About Elixir

  1. Start Small: Experiment with a tiny service or background job. Don’t rewrite your entire monolith on day one.
  2. Get Comfortable with Functional Concepts: Embrace immutability and pattern matching. The mental shift is real, but it pays off.
  3. Check Out Phoenix and LiveView: If you’re doing web dev, see how your typical Rails flow translates in Phoenix. And definitely try LiveView.
  4. Utilise Existing Ruby Skills: Your understanding of test-driven development, domain modeling, and code readability all carry over—you’ll just write them differently.

Ultimately, if you’re running into the same scaling or concurrency issues I did, Elixir might just be the upgrade you need. It brings a breath of fresh air to large-scale, real-time, and fault-tolerant applications while keeping developer happiness front and center. For me, it was worth the leap, and I haven’t looked back since. If you’re looking for a detailed comparison of Elixir and Ruby, our comprehensive Elixir vs. Ruby guide has you covered.

The post My Journey from Ruby to Elixir: Lessons from a Developer appeared first on Erlang Solutions.

by Oleg Ivanov at March 27, 2025 10:58

The XMPP Standards Foundation

Open Letter to Meta: Support True Messaging Interoperability with XMPP

It has been a little over a year since Meta announced their proposal for third-parties to achieve messaging interoperability with WhatsApp, with Facebook Messenger following half a year later. Not for everyone, and only because these services were designated as Gate Keepers under the recent Digital Markets Act (DMA) in the EU. So only in the EU, and then with many strings attached. In that time, a lot has been written. Element/Matrix have put in efforts to work with Meta to get some interoperability going. Unfortunately, the reference offers don’t provide what we would call true interoperability, and given that virtually nobody has taken up Meta on this offer, their proposal just falls short across the board.

Over at the IETF, the More Instant Messaging Interoperability (MIMI) working group is working on mechanisms for interoperability. While several of our members are involved with MIMI and working on the implementation of the related MLS protocol for end-to-end encryption, we believe it is time to have true interoperability using a well-tested and widely implemented set of standards: XMPP.

To that end, we today publish an Open Letter to Meta. A call to action, urging Meta to adopt XMPP for messaging interoperability. For a more in-depth reasoning, we also provide a detailed technical briefing.

We are ready. Let’s make it happen.

March 27, 2025 00:00

March 26, 2025

Mathieu Pasquet

slixmpp v1.10

This new version does not have many new features, but it has quite a few breaking changes, which should not impact many people, as well as one important security fix.

Thanks to everyone who contributed with code, issues, suggestions, and reviews!

Security

After working on TLS stuff, I noticed that we still allowed unencrypted SCRAM to be negociated, which is really not good. For packagers who only want this security fix, the commit fd66aef38d48b6474654cbe87464d7d416d6a5f3 should apply cleanly on any slixmpp version.

(most servers in the wild have unencrypted connections entirely disabled, so this is only an issue for Man in the Middle attacks)

Enhancements

  • slixmpp now supports XEP-0368 and allows to choose easily between direct TLS, or STARTTLS.

Breaking Changes

  • The security issue mentioned above is a breaking change if you actively want to connect to servers without encryption. If that is a desired behavior, you can still set xmpp['feature_mechanisms'].unencrypted_scram = True on init.

  • Removal of the timeout_callback parameter anywhere it was present. Users are encouraged to await on the coroutine or the future returned by the function, which will raise an IqTimeout exception when appropriate.

  • Removal of the custom google plugins, which I am guessing have not worked in a very long time (both the google and gmail_notify plugin).

  • Removal of the Stream Compression (XEP-0138) plugin. It was not working at all and use of compression is actively discouraged for security reasons.

  • Due to the new connection code, the configuration of the connection parameters has changed quite a bit:

    • The XMLStream (from which the ClientXMPP class inherits) does not have a use_ssl parameter anymore. Instead it has enable_direct_tls and enable_starttls as well as enable_plaintext attributes. Those attributes control whether we want to connect using starttls or direct TLS. The plaintext is for components since we only implement the jabber component protocol (XEP-0114).
    • The connect() method signature has changed entirely, and it no longer takes any other parameters than host and port (which must be provided together to have an effect).
    • Handling of custom addresses has changed a bit, now they are set through calling connect(), and kept until connect() is called without arguments again.
    • The DNS code will now fetch both xmpps-client and xmpp-client records (unless direct TLS is explicitly disabled) and prefer direct TLS if it has the same priority as STARTTLS.
    • The SRV targeted by the queries can be customized using the tls_services and starttls_services of ClientXMPP (but have no idea why anyone would do this)

Fixes

  • Another issue encountered with the Rust JID, trying to compare a JID against strings that cannot be parsed or other objects would raise an InvalidJID exception instead of returning False.
  • The ssl_cert event would only be invoked on STARTTLS.
  • One of the asyncio warnings on program exit (that a coroutine is still running).
  • Traceback with BaseXMPP.get.
  • A potential edge case in the disco (XEP-0030) plugin when using strings instead of JIDs.
  • A traceback in vcard-temp (XEP-0054) and Legacy Delayed Delivery (XEP-0091) when parsing datetimes.
  • A traceback when manipulating conditions in feature mechanisms.
  • A traceback in Ad-hoc commands (XEP-0050) during error handling.
  • Many tracebacks in OAuth over XMPP (XEP-0235) due to urllib API changes.

by mathieui at March 26, 2025 20:00