O tamanho máximo de uma mensagem MQTT no protocolo é de 268.435.455 bytes, cerca de 256 MB. Na prática você nunca chega lá: brokers, serviços de nuvem e bibliotecas cliente definem limites menores, e alguns descartam mensagens grandes demais sem avisar. Este guia explica onde cada limite fica, como o MQTT 5 o torna visível e como testar o teto real do seu broker antes que uma imagem de firmware ou um snapshot de câmera o encontre por você.
De onde vem o limite de 256 MB
Todo pacote de controle MQTT começa com um cabeçalho fixo que contém o Remaining Length: o número de bytes que vêm a seguir. Ele é codificado como um inteiro de tamanho variável com no máximo quatro bytes, sete bits úteis cada, então o maior valor é 2^28 − 1 = 268.435.455.
Esse número cobre todo o resto do pacote, não só os seus dados. Um PUBLISH também contém:
- o nome do topic (comprimento de 2 bytes + bytes UTF-8),
- um packet identifier de 2 bytes para QoS 1 e 2,
- no MQTT 5, um bloco de propriedades (content type, user properties, message expiry…).
Portanto, o maior payload possível fica um pouco abaixo de 256 MB e diminui com topics longos e muitas user properties. A calculadora de tamanho de pacotes MQTT mostra o overhead exato para um topic, QoS e payload.
Os limites que você realmente encontra
| Camada | Onde o limite é definido | Comportamento típico ao ultrapassar |
|---|---|---|
| Protocolo | Remaining Length (4 bytes) | O pacote nem pode ser codificado |
| Mosquitto | max_packet_size, antes message_size_limit | MQTT 5: desconexão com 0x95; 3.1.1: mensagem descartada ou conexão fechada |
| EMQX | mqtt.max_packet_size (padrão 1 MB) | Conexão fechada, erro no log do broker |
| HiveMQ | max-packet-size na configuração MQTT | Clientes MQTT 5 recebem 0x95; clientes 3.1.1 são desconectados |
| Serviços IoT em nuvem | Cotas do serviço | O AWS IoT Core limita payloads a 128 KB, o Azure IoT Hub mensagens device-to-cloud a 256 KB; confira as páginas de cotas atuais |
| Biblioteca cliente | Buffers internos, Maximum Packet Size do MQTT 5 | Erro ao publicar ou descarte silencioso ao receber |
| Caminho de rede | Proxies, load balancers, gateways WebSocket | Timeouts ou resets em links lentos |
Os valores padrão mudam entre versões, então use esta tabela como um mapa de onde procurar, não como uma lista de números garantidos. Leia a referência de configuração da versão exata que você roda.
Configuração do Mosquitto
O Mosquitto 2.x tem duas opções relacionadas:
# Maximum size of any MQTT packet the broker accepts, in bytes.
# MQTT 5 clients are told this value in CONNACK.
max_packet_size 1048576
# Older option: maximum PUBLISH payload size. Deprecated in favour of
# max_packet_size, but still found in many existing configs.
# message_size_limit 1048576Se nenhuma delas estiver definida, o Mosquitto não impõe limite menor que o do protocolo, ou seja, um único cliente pode fazer o broker alocar centenas de megabytes. Definir um limite explícito faz parte de uma configuração de produção sensata; o gerador de mosquitto.conf já inclui isso.
Maximum Packet Size no MQTT 5
O MQTT 3.1.1 não tem como negociar tamanho. O MQTT 5 adiciona a propriedade Maximum Packet Size nas duas direções:
- CONNECT → broker: o cliente anuncia o maior pacote que aceita receber. O broker não pode enviar nada maior; se uma mensagem correspondente for grande demais para esse subscriber, o broker a descarta apenas para esse cliente.
- CONNACK → cliente: o broker anuncia o maior pacote que aceita. Uma biblioteca cliente bem implementada se recusa a enviar pacotes maiores. Se mesmo assim um for enviado, o broker desconecta com o reason code 0x95 Packet too large.
Esse segundo caso é o erro que as pessoas pesquisam. O significado dele e os códigos relacionados estão na referência de reason codes MQTT e são explicados em detalhe em MQTT packet too large.
Teste rápido com mosquitto_pub
Gere arquivos de tamanhos conhecidos e envie-os pelo broker. -f envia um arquivo como payload; -N impede que o mosquitto_sub acrescente uma quebra de linha, então a contagem de bytes fica exata.
HOST=broker.connectmq.com
TOPIC="testmqtt/payload-$RANDOM/blob"
for size in 64K 512K 1M 4M; do
head -c "$size" /dev/urandom > "/tmp/blob-$size"
done
# Terminal 1: receber uma mensagem e contar os bytes
mosquitto_sub -h "$HOST" -t "$TOPIC" -V mqttv5 -C 1 -W 30 -N | wc -c
# Terminal 2: enviar um tamanho por vez
mosquitto_pub -h "$HOST" -t "$TOPIC" -V mqttv5 -q 1 -f /tmp/blob-1M -d-d mostra cada pacote enviado e recebido, então você vê se o PUBLISH saiu do cliente e se a conexão foi fechada logo depois. Se o wc -c imprimir o tamanho do arquivo, a mensagem chegou; se o mosquitto_sub expirar após 30 segundos, não chegou. Para simular um subscriber limitado, adicione -D connect maximum-packet-size 65536 ao mosquitto_sub e veja as mensagens maiores sumirem só para esse cliente.
Varredura automática de tamanhos em Python
Para ter uma resposta reproduzível, este script com paho-mqtt 2.x publica payloads de tamanho crescente com QoS 1, verifica cada um com um hash SHA-256 e para na primeira falha. Ele também mostra o limite anunciado pelo broker.
import hashlib, os, threading, time, uuid
import paho.mqtt.client as mqtt
HOST, PORT = "broker.connectmq.com", 1883
TOPIC = f"testmqtt/payload-{uuid.uuid4().hex[:8]}/blob"
SIZES = [1_024, 65_536, 262_144, 1_048_576, 4_194_304, 16_777_216]
TIMEOUT = 30
result, got = {}, threading.Event()
def on_connect(client, userdata, flags, reason_code, properties):
limit = getattr(properties, "MaximumPacketSize", None)
print(f"connected: {reason_code}, broker max packet = {limit or 'not advertised'}")
def on_disconnect(client, userdata, flags, reason_code, properties):
print(f"disconnected: {reason_code}")
def on_message(client, userdata, msg):
result["digest"] = hashlib.sha256(msg.payload).hexdigest()
got.set()
def make_client(name):
c = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2,
client_id=f"{name}-{uuid.uuid4().hex[:6]}", protocol=mqtt.MQTTv5)
# c.username_pw_set(os.environ["MQTT_USER"], os.environ["MQTT_PASS"])
c.on_connect, c.on_disconnect, c.on_message = on_connect, on_disconnect, on_message
c.connect(HOST, PORT)
c.loop_start()
return c
sub = make_client("sweep-sub")
sub.subscribe(TOPIC, qos=1)
pub = make_client("sweep-pub")
time.sleep(2)
for size in SIZES:
payload = os.urandom(size)
got.clear()
start = time.perf_counter()
info = pub.publish(TOPIC, payload, qos=1)
if info.rc != mqtt.MQTT_ERR_SUCCESS:
print(f"{size:>10} B FAIL publish rc={info.rc}")
break
if not got.wait(TIMEOUT):
print(f"{size:>10} B FAIL not delivered within {TIMEOUT}s")
break
ok = result["digest"] == hashlib.sha256(payload).hexdigest()
print(f"{size:>10} B {'OK ' if ok else 'BAD '} {(time.perf_counter() - start) * 1000:.0f} ms")
pub.loop_stop(); sub.loop_stop()Saídas típicas e o que significam:
- Todos os tamanhos OK: o broker aceita pelo menos 16 MB. Decida se é isso mesmo que você quer.
- Entregue até N, depois "not delivered", sem desconexão: o broker descarta silenciosamente mensagens grandes demais, ou o limite do próprio subscriber entrou em ação.
- "disconnected: Packet too large": um broker MQTT 5 aplicando
max_packet_size. O último tamanho que passou é o seu teto prático. - A latência cresce muito com o tamanho: você está medindo largura de banda, não o broker. Compare os números com a velocidade de upload da sua conexão.
Rode a varredura uma vez via TCP e outra via WebSockets (porta 8083 ou 8084 com o path /mqtt): proxies na frente de listeners WebSocket às vezes têm seus próprios limites de frame ou de buffer. Você também pode testar payloads individuais de forma interativa no cliente MQTT online.
Payloads grandes têm efeitos colaterais
Mesmo quando o broker aceita uma mensagem de 10 MB, ela não sai de graça:
- Bloqueio head-of-line. O MQTT roda sobre uma única conexão TCP. Enquanto um PUBLISH grande está sendo transmitido, nada mais anda nessa conexão, nem comandos pequenos e urgentes, nem pacotes PINGREQ. Em um link celular lento isso pode causar timeouts de keep-alive.
- Memória. O broker normalmente mantém a mensagem inteira em memória, uma vez para cada subscriber na fila com sessão persistente offline. Mensagens retidas grandes ficam lá indefinidamente.
- Retransmissões. Com QoS 1 ou 2, uma conexão perdida significa reenviar o pacote inteiro: não existe retomada.
- Fan-out. Uma mensagem de 5 MB para 200 subscribers são 1 GB de tráfego de saída. Veja o overhead de banda do MQTT para fazer as contas.
Padrões de design para dados grandes
- Mantenha as mensagens pequenas por padrão. Telemetria, eventos e comandos devem ter bytes ou kilobytes. Codificações binárias como CBOR ou Protobuf reduzem bastante payloads JSON.
- Divida arquivos grandes. Separe em partes numeradas (por exemplo de 64 KB) em
…/file/<id>/<n>, envie um manifesto com o tamanho total e o hash, e remonte no receptor. Transferência de arquivos via MQTT mostra uma implementação completa. - Envie um ponteiro, não o arquivo. Faça upload para um armazenamento de objetos via HTTP e publique a URL com os metadados via MQTT. É a escolha usual para imagens de câmera e firmware.
- Defina um limite explícito no broker um pouco acima da sua maior mensagem legítima, para que um cliente com defeito não consiga esgotar a memória.
Publique um payload de teste no navegador
O teto de 256 MB do protocolo é um número teórico; o limite que importa é o menor de todo o caminho, do buffer do cliente à configuração do broker e à cota da nuvem. Meça com uma varredura de tamanhos, deixe-o explícito na configuração do broker e projete qualquer coisa maior como partes ou ponteiros, em vez de uma única mensagem.
Perguntas frequentes
Qual é o tamanho máximo de uma mensagem MQTT?
O protocolo permite pacotes de controle de até 268.435.455 bytes (cerca de 256 MB), porque o campo Remaining Length tem no máximo quatro bytes. O payload útil é um pouco menor, e quase todo broker ou serviço de nuvem impõe um limite bem mais baixo.
Por que minha mensagem MQTT grande some sem nenhum erro?
No MQTT 3.1.1 o broker não tem como rejeitar um PUBLISH específico informando o motivo, então muitos brokers descartam silenciosamente mensagens grandes demais ou fecham a conexão. Use MQTT 5, leia o Maximum Packet Size do CONNACK e fique atento ao reason code 0x95 Packet too large.
Devo enviar arquivos ou imagens por MQTT?
Arquivos pequenos, de algumas centenas de kilobytes, funcionam bem na maioria dos brokers. Para arquivos maiores, divida-os em partes numeradas ou publique uma URL para um armazenamento de objetos, para que uma mensagem enorme não bloqueie a conexão nem esgote a memória do broker.

