Kokil Thapa - Professional Web Developer in Nepal
Freelancer Web Developer in Nepal with 15+ Years of Experience

Kokil Thapa is an experienced full-stack web developer focused on building fast, secure, and scalable web applications. He helps businesses and individuals create SEO-friendly, user-focused digital platforms designed for long-term growth.

MQTT for IoT Messaging

By Kokil Thapa | Last reviewed: September 2026

MQTT for IoT messaging solves a problem HTTP was never designed for: thousands of tiny devices sending short updates over flaky mobile or Wi-Fi links while running on battery. Sensors, gateways, and dashboards need a protocol that keeps payloads small, reconnects quietly, and does not require the device to poll a server every few seconds. If you build connected products, fleet trackers, or smart-building dashboards, you will eventually evaluate MQTT alongside the lightweight messaging patterns you already use in web backends. This guide covers how MQTT works, how to run a broker safely, and how it connects to the PHP and Laravel stacks many teams already maintain.

What is MQTT and why is it the default for IoT messaging?

MQTT stands for Message Queuing Telemetry Transport. Despite the name, it is not a traditional message queue. It is a pub/sub wire protocol designed in 1999 for oil-pipeline telemetry and standardised by OASIS MQTT v5.0. Version 5 adds session expiry, user properties, and shared subscriptions; most production fleets still run MQTT 3.1.1 because every embedded SDK supports it.

The protocol fits IoT because a single PUBLISH frame can carry a few bytes of sensor data. A typical JSON reading over HTTPS needs headers, TLS, and a full HTTP round trip. MQTT keeps the connection open and sends only what changed. On a 2G link in rural Nepal or a congested factory floor, that difference shows up in billable data and device uptime.

MQTT for IoT Messaging — Core TopologyIoT Devicesensor / actuatorGatewayedge aggregatorMQTT BrokerMosquitto / EMQXDashboardweb UILaravel AppPHP consumerRules Enginealerts / jobs
MQTT for IoT messaging uses a central broker so many publishers and subscribers never need direct connections to each other.

Three roles define every deployment:

  • Publisher — a device or service that sends messages to a topic.
  • Subscriber — any client that receives messages matching a topic filter.
  • Broker — the server that accepts connections, enforces ACLs, and routes messages.

Devices never talk to each other directly. They talk to the broker. That indirection is what makes MQTT scale: add ten thousand sensors without reconfiguring your dashboard.

Where MQTT shows up in real products

MQTT appears in smart agriculture soil probes, cold-chain temperature loggers, parking occupancy sensors, and industrial PLCs bridged to cloud dashboards. On booking and logistics platforms I have worked on, GPS trackers and SMS gateways often expose MQTT as one ingestion path while the web app still runs on Laravel and MySQL. The protocol layer stays separate from the business logic layer, which is exactly how you want it.

How does the MQTT publish-subscribe model work?

Every message belongs to a topic, a UTF-8 string with slash-separated levels. A temperature reading from warehouse three might publish to site/kathmandu/wh3/temp. Subscribers use filters:

  • site/kathmandu/wh3/temp — exact match.
  • site/kathmandu/+/temp — single-level wildcard.
  • site/# — multi-level wildcard.

Design topics for operations, not for individual device serial numbers alone. A pattern like org/{orgId}/device/{deviceId}/telemetry keeps ACL rules readable and makes it easy to subscribe to all devices in one org.

Quality of Service levels

MQTT defines three QoS levels. Pick the lowest level that meets your reliability requirement; higher QoS costs bandwidth and broker storage.

QoSNameDelivery guaranteeTypical IoT use
0At most onceFire and forget; may lose messagesHigh-frequency telemetry where the next reading replaces the last
1At least onceAcknowledged; duplicates possibleAlerts, door events, billing triggers
2Exactly onceFour-part handshake; no duplicatesFinancial or safety-critical commands

Most sensor streams use QoS 0 or 1. I have seen teams default everything to QoS 2 and then wonder why broker CPU spikes. Match QoS to business impact, not to maximum safety reflex.

MQTT QoS Delivery FlowQoS 0At most oncePUBLISHDone — no ACKQoS 1At least oncePUBLISHPUBACKMay duplicateQoS 2Exactly oncePUBLISHPUBRECPUBRELPUBCOMPNo duplicates
Choosing the right MQTT QoS level balances delivery guarantees against bandwidth and broker load in IoT deployments.

Retained messages and Last Will

A retained message stores the last payload on a topic so new subscribers get the current state immediately. Use it for device online status or last-known configuration, not for high-frequency streams.

Last Will and Testament (LWT) tells the broker to publish a message if the client disconnects unexpectedly. A common pattern publishes to devices/{id}/status with payload offline when a sensor drops off the network without a clean DISCONNECT.

Keep-alive and clean sessions

Clients send PINGREQ frames within the keep-alive interval to prove they are alive. Set keep-alive based on network behaviour: 30–60 seconds on stable Wi-Fi, longer on NB-IoT if your broker allows it. With MQTT 5, session expiry replaces the older clean-session flag and gives you explicit control over offline message buffering.

How do you set up an MQTT broker for production IoT workloads?

The broker is infrastructure, not application code. Treat it like you treat Redis or MySQL: hardened host, TLS, monitoring, and backups of configuration at minimum.

Broker options compared

BrokerBest forClusteringNotes
Eclipse MosquittoSingle-node, edge, dev/stagingLimited bridge modeLightweight, widely packaged on Ubuntu
EMQXHigh-connection cloud deploymentsNative clusteringBuilt-in rule engine and HTTP webhook bridge
HiveMQEnterprise SLA requirementsYesCommercial support and extensions
AWS IoT CoreAWS-native fleetsManagedPer-message pricing; tight IAM integration

For a first production deployment on a VPS you manage yourself, Mosquitto on Ubuntu 24 with TLS from Let's Encrypt is a sane starting point. Move to EMQX or a managed service when connection counts exceed what one node handles comfortably. Linux server administration for broker hardening follows the same patterns as any other public-facing daemon: non-root service user, UFW, fail2ban, and log rotation.

Install Mosquitto with TLS on Ubuntu

# Install broker and clients
sudo apt update
sudo apt install -y mosquitto mosquitto-clients

# Create password file
sudo mosquitto_passwd -c /etc/mosquitto/passwd device_001

# /etc/mosquitto/conf.d/production.conf
listener 8883
certfile /etc/letsencrypt/live/mqtt.example.com/fullchain.pem
keyfile /etc/letsencrypt/live/mqtt.example.com/privkey.pem
require_certificate false
allow_anonymous false
password_file /etc/mosquitto/passwd

# ACL file — devices publish only to their own branch
# /etc/mosquitto/acl
user device_001
topic write site/kathmandu/device_001/#
topic read site/kathmandu/device_001/config

sudo systemctl restart mosquitto

Test from your laptop before you flash firmware:

mosquitto_pub -h mqtt.example.com -p 8883 \
  --cafile /path/to/ca.crt -u device_001 -P 'secret' \
  -t 'site/kathmandu/device_001/telemetry' \
  -m '{"temp":24.1,"hum":62}' -q 1

Validate inbound JSON with a JSON formatter and linter during development so malformed payloads never reach your database writers.

Production MQTT Security StackTLS 1.2+ on port 8883 — encrypt transportUsername / password or client certificatesTopic ACLs — least privilege per deviceNetwork firewall — restrict 8883 to known IPsNever expose unauthenticated MQTT on port 1883 to the public internet
Secure MQTT for IoT messaging stacks TLS, authentication, ACLs, and firewall rules before devices connect from the field.

Operational checklist

  1. Enable TLS on port 8883; block plain 1883 from the public internet.
  2. Issue unique credentials or client certificates per device batch.
  3. Define ACL files so a compromised sensor cannot publish to foreign topics.
  4. Set connection limits and message size caps in broker config.
  5. Ship logs to your existing stack; pair with Prometheus-style alerting on connection count and publish rate.
  6. Document topic naming in your internal wiki before firmware teams diverge.

Reference the Eclipse Mosquitto documentation for directive names; they change little between releases but defaults are not production-safe out of the box.

When should you choose MQTT over HTTP or WebSockets for IoT?

HTTP works when devices send data rarely and already speak REST. MQTT wins when connections stay open, payloads stay under a kilobyte, and you publish more often than once per minute per device.

CriteriaMQTTHTTPS RESTWebSockets
Payload overhead2-byte header minimumFull HTTP headers each requestLow after upgrade
Push to deviceNative via subscribed topicsRequires polling or separate channelNative bidirectional
Offline bufferingBroker queues for clean sessionsClient must retry POSTApp must implement queue
Firewall traversalOften blocked except 8883Port 443 usually openSame as HTTP upgrade
PHP/Laravel fitLong-running worker subscriberNatural request/responseRatchet, Swoole, or external service

A pattern I use on hybrid projects: MQTT from device to broker, then an EMQX rule or a small Node.js 26 LTS bridge publishes normalized events to a Laravel HTTP endpoint. The web app stays stateless PHP-FPM. The messaging tier handles connection churn. That split mirrors how multi-channel notifier architectures keep delivery mechanics out of controllers.

Choose WebSockets when you need a browser tab to stream live data and you control both ends. Choose MQTT when firmware teams, third-party hardware vendors, or mobile SDKs already standardise on it. Trying to force HTTP on a vendor that ships MQTT firmware costs more engineering time than standing up a broker.

How do you integrate MQTT with Laravel or PHP applications?

PHP request/response workers are the wrong place to hold a persistent MQTT connection. Run a dedicated consumer process instead, then hand events to queues your Laravel 13 app already understands.

Architecture that survives deploys

On production Laravel applications I maintain, long-lived processes run under systemd or Supervisor. They subscribe to MQTT topics, validate payloads, and dispatch Laravel jobs to Redis. The web tier never blocks on broker I/O. This matches how you'd integrate any high-volume webhook stream — same idempotency rules, same rate-limit and abuse patterns, different wire format.

# composer require php-mqtt/client (PHP 8.3+)
# app/Console/Commands/MqttConsumeCommand.php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use PhpMqtt\Client\MqttClient;
use App\Jobs\ProcessTelemetryReading;

class MqttConsumeCommand extends Command
{
    protected $signature = 'mqtt:consume';
    protected $description = 'Subscribe to telemetry topics';

    public function handle(): int
    {
        $client = new MqttClient(
            config('mqtt.host'),
            config('mqtt.port'),
            config('mqtt.client_id')
        );

        $client->connect(
            config('mqtt.username'),
            config('mqtt.password')
        );

        $client->subscribe('site/+/+/telemetry', function ($topic, $message) {
            $payload = json_decode($message, true);

            if (! is_array($payload)) {
                return;
            }

            ProcessTelemetryReading::dispatch($topic, $payload);
        }, 1);

        $client->loop(true);

        return self::SUCCESS;
    }
}

Run it as a supervised service:

# /etc/systemd/system/mqtt-consumer.service
[Unit]
Description=Laravel MQTT consumer
After=network.target mosquitto.service

[Service]
User=www-data
WorkingDirectory=/var/www/app/current
ExecStart=/usr/bin/php artisan mqtt:consume
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

Idempotency and ordering

QoS 1 can deliver duplicates. Store a device message ID or a hash of topic plus timestamp in Redis before you write MySQL. Reject duplicates at the job layer. Ordering is per topic, not global. If sequence matters, include a monotonic counter in the payload and reject stale readings in application code.

For dashboards, push processed readings to the browser over Laravel Echo and Redis broadcasting. Keep MQTT on the server side only unless you have a compelling reason to expose brokers to browsers.

MQTT → Laravel Integration PipelineIoT DevicePUBLISHMQTT Brokerroute topicPHP Consumerartisan mqtt:consumeRedis Queuededupe keysMySQLtelemetry rowsLaravel HTTP API + Blade dashboardreads MySQL — never holds MQTT socket
Integrating MQTT for IoT messaging with Laravel works best when a long-lived consumer feeds queues while PHP-FPM handles HTTP as usual.

Bridging MQTT to business workflows

Once telemetry lands in your database, it is just data. Trigger automation rules when cold-storage temperature exceeds a threshold. Send SMS alerts through the same notifier pipeline you use for booking confirmations. On a trek-management platform like Adventure Third Pole Trek, GPS breadcrumbs might arrive over MQTT while staff manage bookings in Livewire — two channels, one source of truth in MySQL.

If you need a managed bridge without writing a consumer, EMQX rules can HTTP POST into Laravel routes protected by signed tokens, similar to payment gateway callbacks you already verify server-side. Treat those endpoints like webhooks: authenticate, validate schema, respond quickly, queue heavy work. The same discipline applies to API authentication choices elsewhere in your stack.

Key Takeaways

  • MQTT for IoT messaging uses pub/sub topics and a central broker so devices and apps stay decoupled at scale.
  • Default sensor streams to QoS 0 or 1; reserve QoS 2 for commands where duplicates cause real harm.
  • Never expose an unauthenticated broker on port 1883 — TLS, ACLs, and per-device credentials are mandatory.
  • Keep persistent MQTT connections out of PHP-FPM; run a supervised artisan consumer that dispatches Laravel jobs.
  • Design topic hierarchies and idempotent job handlers before firmware teams ship incompatible naming schemes.
  • Bridge MQTT into HTTP or queues when your main app is Laravel, WordPress, or another request-driven stack.

People Also Ask

Is MQTT secure enough for production IoT?

MQTT has no built-in encryption or authentication by itself. Production security comes from TLS on port 8883, strong client credentials, topic ACLs, and network isolation. Treat the broker like any public API surface. Patch it, monitor it, and rotate device passwords when hardware is decommissioned.

What is the difference between MQTT and CoAP?

MQTT runs over TCP and suits always-on gateways and Wi-Fi devices with steady connections. CoAP uses UDP and fits constrained microcontrollers on lossy links where connection overhead matters more. Many deployments use both: CoAP at the edge, MQTT from gateway to cloud.

Can MQTT work over cellular networks in Nepal?

Yes. NTC and Ncell data SIMs support TCP to port 8883 when APN settings allow it. Size payloads small, use QoS 1 sparingly, and set generous keep-alive values on unstable links. Test on the actual carrier before you deploy five hundred field units around Kathmandu Valley or the Terai.

How many connections can one Mosquitto instance handle?

A modest Ubuntu VPS with 2 GB RAM often handles a few thousand concurrent clients if messages are small and QoS stays low. Beyond that, profile CPU and file descriptors, then move to EMQX clustering or a managed cloud broker. Connection count matters more than message rate for sizing.

Build connected products without betting the farm on the wrong protocol

MQTT for IoT messaging earns its place when devices publish often, payloads stay tiny, and you need push semantics without polling a REST API all day. Stand up a secured broker, nail your topic contract, and bridge into the Laravel or PHP backend you already operate. Keep long-lived subscribers out of web workers, dedupe at the job layer, and monitor broker health like any other production dependency. If you are planning telemetry for logistics, agriculture, smart buildings, or a custom hardware integration, enterprise application development and API integration work can cover broker setup through dashboard delivery. See related builds on the portfolio or contact us to talk through architecture before you commit firmware to a topic scheme you cannot change later.

Frequently Asked Questions

MQTT is a lightweight publish-subscribe protocol over TCP that sends small binary frames to a central broker using topic-based routing and three QoS levels for battery-powered IoT devices.

Enable TLS on port 8883. Block plain MQTT on port 1883 from the public internet.

QoS 0 delivers at most once. QoS 1 delivers at least once with possible duplicates. QoS 2 delivers exactly once through a four-part handshake.

Every message belongs to a UTF-8 topic string with slash-separated levels, such as site/kathmandu/wh3/temp. Publishers send to topics; subscribers use filters with single-level plus or multi-level hash wildcards. Devices never connect to each other directly. They connect to a central broker that routes messages, enforces ACLs, and scales as you add sensors without reconfiguring dashboards. Design topics for operations, like org/{orgId}/device/{deviceId}/telemetry, not serial numbers alone.

MQTT wins when connections stay open, payloads stay under a kilobyte, and devices publish more often than once per minute. HTTP suits rare REST-style updates. WebSockets fit browser tabs streaming live data when you control both ends. On hybrid Laravel projects, I often run MQTT from device to broker, then bridge normalized events into PHP via EMQX rules or a Node.js 26 LTS service. PHP-FPM stays stateless while the messaging tier handles connection churn firmware vendors already expect.

Treat the broker like Redis or MySQL: hardened host, TLS, monitoring, and backed-up configuration. On a VPS, Eclipse Mosquitto on Ubuntu 24 with Let's Encrypt certificates is a sane first step. Install mosquitto and mosquitto-clients, create a password file with mosquitto_passwd, define listener 8883 with certfile and keyfile, set allow_anonymous false, and write ACL files so each device publishes only to its own topic branch. Test with mosquitto_pub over TLS before flashing firmware.

MQTT has no built-in encryption or authentication by itself. Production security comes from TLS on port 8883, strong per-device credentials or client certificates, topic ACLs, connection limits, message size caps, and network isolation via UFW and fail2ban. Treat the broker like any public API surface: patch it, ship logs to your monitoring stack, alert on connection count and publish rate, and rotate device passwords when hardware is decommissioned. Never expose an unauthenticated broker on port 1883.

Eclipse Mosquitto suits single-node edge, dev, and staging with limited bridge mode. EMQX fits high-connection cloud deployments with native clustering and built-in rule engines plus HTTP webhook bridges. HiveMQ targets enterprise SLA needs with commercial support. AWS IoT Core suits AWS-native fleets with managed per-message pricing and IAM integration. Start self-hosted Mosquitto on a VPS; move to EMQX or a managed service when connection counts exceed what one node handles comfortably.

PHP-FPM request workers are the wrong place for persistent MQTT connections. Run a supervised long-lived consumer under systemd or Supervisor that subscribes via php-mqtt/client on PHP 8.3+, validates JSON payloads, and dispatches Laravel 13 jobs to Redis. The web tier never blocks on broker I/O. For dashboards, push processed readings through Laravel Echo and Redis broadcasting. Keep MQTT on the server side unless you have a strong reason to expose brokers to browsers. EMQX can also HTTP POST into signed Laravel webhook routes.

MQTT runs over TCP and suits always-on gateways and Wi-Fi devices with steady connections. CoAP uses UDP and fits constrained microcontrollers on lossy links where connection overhead matters more. Many deployments use both: CoAP at the edge, MQTT from gateway to cloud. If your firmware vendor or mobile SDK already standardises on MQTT, forcing HTTP costs more engineering time than standing up a broker.

Yes. NTC and Ncell data SIMs support TCP connections to external hosts, which MQTT requires. On 2G or congested links in rural Nepal, MQTT's small binary frames and persistent connections use less billable data than HTTPS REST on every sensor reading. Set keep-alive intervals based on network behaviour: 30 to 60 seconds on stable links, longer on NB-IoT if your broker allows it. Validate reconnect logic in firmware before field deployment.

A retained message stores the last payload on a topic so new subscribers immediately receive current state. Use retained messages for device online status or last-known configuration, not high-frequency telemetry streams. Last Will and Testament tells the broker to publish a message if a client disconnects unexpectedly, such as publishing offline to devices/{id}/status when a sensor drops without a clean DISCONNECT. Pair LWT with keep-alive PINGREQ frames so the broker detects dead connections quickly.

Use slash-separated levels that reflect operations, not individual serial numbers alone. A pattern like org/{orgId}/device/{deviceId}/telemetry keeps ACL rules readable and lets dashboards subscribe to all devices in one organisation. Document naming in your internal wiki before firmware teams diverge. Match ACL files so each credential can write only its own branch and read its config topics. Wildcard filters like site/kathmandu/+/temp or site/# let operators subscribe at the right granularity without per-device broker changes.

QoS 1 acknowledges delivery but can produce duplicates. Store a device message ID or a hash of topic plus timestamp in Redis before writing MySQL, then reject duplicates at the job layer. Ordering is guaranteed per topic, not globally; include a monotonic counter in payloads and reject stale readings in application code if sequence matters. Default sensor streams to QoS 0 or 1 and reserve QoS 2 for commands where duplicates cause real harm, because higher QoS increases bandwidth and broker CPU load.

MQTT 5.0 is standardised by OASIS and adds session expiry, user properties, and shared subscriptions. Most production IoT fleets still run MQTT 3.1.1 because every embedded SDK supports it. With MQTT 5, session expiry replaces the older clean-session flag and gives explicit control over offline message buffering. Unless you need v5-specific features like shared subscriptions across consumer nodes, staying on 3.1.1 keeps firmware and broker compatibility straightforward across mixed-vendor hardware.

Share this article

0 Comments

Leave a comment

Your email is not published. Comments appear once they have been read. Sign in to have your details filled in.

Quick Contact Options
Choose how you want to connect me: