La forma más limpia de usar MQTT en desarrollo, staging y producción se resume rápido: da a cada entorno su propio broker (o instancia aislada de broker) y sus propias credenciales, mantén los nombres de topic idénticos entre entornos y cambia solo la configuración (URL, usuario, contraseña) cuando el código pasa de uno a otro. Todo lo demás en esta guía consiste en que eso sea aburrido y seguro.
Para qué sirve cada entorno
| Desarrollo | Staging | Producción | |
|---|---|---|---|
| Propósito | Iteración rápida, experimentos | Release candidate, pruebas de integración y de carga | Dispositivos y clientes reales |
| Broker | Docker local o un endpoint de pruebas compartido | Mismo tipo de broker y misma configuración que producción | Dedicado y monitorizado |
| Datos | Falsos, desechables | Realistas, generados o anonimizados | Reales |
| Quién se conecta | Desarrolladores, simuladores | CI, dispositivos de prueba, QA | Flota y servicios de backend |
| Credenciales | Por desarrollador o un usuario de desarrollo compartido | Por servicio, solo de staging | Por servicio y por dispositivo |
| TLS | Opcional | Obligatorio, igual que en producción | Obligatorio |
Staging solo es útil si se comporta como producción. Un broker de staging sin TLS, sin autenticación o con ACL totalmente abiertas dejará pasar releases que fallan el primer día en producción.
Tres formas de separar los entornos
| Modelo | Cómo funciona | Ideal para | Cuidado con |
|---|---|---|---|
| Un broker por entorno | Hosts o instancias separados; topics idénticos | Producción, y cualquier equipo que pueda permitírselo | Más endpoints que gestionar |
| Broker compartido, topics con prefijo | dev/..., stg/... en un broker, ACL por entorno | Desarrollo y staging con poco presupuesto | Una ACL mal configurada filtra datos entre entornos; capacidad compartida |
| Híbrido | Producción aislada; desarrollo y staging comparten broker | La mayoría de equipos pequeños y medianos | Mantén las credenciales de producción totalmente fuera del broker compartido |
Elijas lo que elijas, producción nunca comparte broker con las pruebas. Una prueba de carga, un simulador desbocado o un mensaje retenido publicado por error no deberían poder llegar a dispositivos reales.
Prefijos de topic bien hechos
Con un broker por entorno, no pongas el entorno en el topic. factory/line1/temp es el mismo topic en staging y en producción, así que suscripciones, dashboards, reglas y ficheros ACL se pueden promover sin tocarlos.
Cuando los entornos comparten broker, el prefijo es obligatorio, y debe añadirse en un único lugar. El peor patrón son las comprobaciones de entorno repartidas por el código (if env == "prod": topic = ...). Construye cada topic con un helper que anteponga el prefijo configurado, y deja el prefijo vacío cuando el entorno tenga su propio broker:
import mqtt from "mqtt";
export const ENV = process.env.APP_ENV ?? "dev";
const url = process.env.MQTT_URL;
const prefix = process.env.MQTT_TOPIC_PREFIX ?? ""; // "" si el entorno tiene su propio broker
if (!url) throw new Error("MQTT_URL is not set");
export const topic = (t) => (prefix ? `${prefix}/${t}` : t);
export function connect(name) {
return mqtt.connect(url, {
clientId: `${name}-${ENV}-${Math.random().toString(16).slice(2, 8)}`,
username: process.env.MQTT_USER,
password: process.env.MQTT_PASS,
protocolVersion: 5,
reconnectPeriod: 2000,
});
}import { connect, topic } from "./mqtt-config.mjs";
const client = connect("ingest");
client.on("connect", () => client.subscribe(topic("factory/+/temp"), { qos: 1 }));Incluir el entorno en el client ID también hace legibles los logs del broker: ves de inmediato que ingest-stg-3fa9c1 es un servicio de staging. En un broker de desarrollo compartido, da a cada desarrollador un prefijo personal como testmqtt/dev-alice para que los experimentos nunca colisionen; los detalles están en nombrar topics de prueba para que nunca colisionen.
Credenciales y ACL por entorno
Cada entorno tiene sus propios usuarios, y una credencial de un entorno debe ser inútil en otro. Nombra a los usuarios por servicio y entorno (ingest-stg, ingest-prod) para que una credencial filtrada o mal usada salte a la vista en los logs.
En un broker compartido de desarrollo y staging, las ACL son lo que realmente mantiene separados los entornos. Un fichero ACL de Mosquitto para ese caso:
user ingest-dev
topic read dev/telemetry/#
topic write dev/cmd/#
user ingest-stg
topic read stg/telemetry/#
topic write stg/cmd/#Verifica la separación en lugar de darla por hecha: conéctate con el usuario de desarrollo e intenta suscribirte a stg/#. Con MQTT 5 el broker devuelve un código de fallo en el SUBACK (0x87 Not authorized); con MQTT 3.1.1 recibes 0x80 o simplemente ningún mensaje. Probar los permisos ACL de MQTT muestra cómo automatizar estas pruebas negativas.
Configuración por entorno
Mantén un fichero de configuración por entorno y cárgalo al arrancar; el código no cambia.
APP_ENV=dev
MQTT_URL=mqtt://broker.connectmq.com:1883
MQTT_USER=username
MQTT_PASS=password
MQTT_TOPIC_PREFIX=testmqtt/dev-aliceAPP_ENV=staging
MQTT_URL=mqtts://<your-staging-host>:8883
MQTT_USER=ingest-stg
MQTT_PASS=<desde tu gestor de secretos>
MQTT_TOPIC_PREFIX=Los valores de producción viven solo en el gestor de secretos del despliegue de producción, nunca en el repositorio ni en los jobs de prueba de CI. Añade una protección al setup de pruebas para que un error no pueda apuntar la suite a producción:
import { ENV } from "../mqtt-config.mjs";
if (ENV === "prod" || ENV === "production") {
throw new Error("Refusing to run tests against production");
}Los dispositivos necesitan la misma disciplina. El firmware no debería llevar el broker fijo en el código; el entorno se asigna durante el aprovisionamiento junto con las credenciales del dispositivo, de modo que un dispositivo de staging no pueda acabar en la flota de producción. Consulta aprovisionamiento de dispositivos MQTT.
Promover la configuración del broker
La configuración del broker (listeners, TLS, límites, ficheros ACL) debe pasar por los entornos igual que el código:
- Guarda la configuración del broker en git como una plantilla más valores por entorno (hostnames, rutas de certificados, límites). El generador de configuración de Mosquitto es una forma rápida de obtener un fichero inicial correcto.
- Revisa los cambios de ACL como si fueran código: un solo
#en la línea equivocada lo abre todo. - Aplica el cambio en desarrollo, luego en staging, ejecuta las pruebas y solo entonces promueve el mismo commit a producción.
- Compara staging con producción antes de cada release. Cualquier diferencia que no sea un hostname, un secreto o un límite de capacidad es un bug esperando a ocurrir.
Smoke test en cada entorno
Tras cada despliegue, ejecuta una ida y vuelta completa con las credenciales de ese entorno. El mismo script sirve en todas partes:
#!/usr/bin/env bash
set -euo pipefail
: "${MQTT_HOST:?}" "${MQTT_USER:?}" "${MQTT_PASS:?}"
T="${MQTT_TOPIC_PREFIX:-testmqtt}/smoke/$(date +%s)"
OUT=$(mktemp)
mosquitto_sub -h "$MQTT_HOST" -p 8883 --capath /etc/ssl/certs \
-u "$MQTT_USER" -P "$MQTT_PASS" -t "$T" -C 1 -W 10 > "$OUT" &
sleep 1
mosquitto_pub -h "$MQTT_HOST" -p 8883 --capath /etc/ssl/certs \
-u "$MQTT_USER" -P "$MQTT_PASS" -t "$T" -m ok -q 1
wait
grep -qx ok "$OUT" && echo "smoke test passed on $MQTT_HOST"-W 10 hace que el suscriptor termine con error si no llega nada en diez segundos, así que un entorno roto hace fallar el pipeline en lugar de bloquearlo. Para una versión más completa, consulta un script de smoke test MQTT; para una comprobación manual, conéctate con el cliente MQTT online usando las credenciales del entorno.
Errores frecuentes
- Las mismas credenciales en todas partes. Una contraseña de desarrollo filtrada se convierte en un incidente de producción.
- Staging sin TLS ni autenticación. Los fallos de certificados y permisos aparecen entonces por primera vez en producción.
- Comprobaciones de entorno en la lógica de negocio. Promueve configuración, no ramas de código.
- Datos de prueba retenidos en un broker compartido. Bórralos tras las pruebas o las siguientes ejecuciones leerán un estado obsoleto.
- Dispositivos de staging olvidados. El hardware de pruebas que apunta a producción por una configuración antigua contamina los datos reales.
Antes de salir en vivo, repasa el checklist de producción MQTT contra el propio entorno de producción, no contra staging.
Brokers separados, credenciales separadas, topics idénticos y un único lugar donde cambia la configuración: con estas cuatro reglas, llevar una release de desarrollo a staging y a producción es un cambio de configuración y un smoke test, no una migración.
Preguntas frecuentes
¿Deben compartir desarrollo, staging y producción un mismo broker MQTT?
Producción debe tener su propio broker o instancia aislada. Desarrollo y staging pueden compartir un broker si cada entorno tiene sus propias credenciales, su propio prefijo de topic y ACL que los separen, aunque las instancias separadas son más fáciles de razonar.
¿El nombre del entorno debe formar parte del topic MQTT?
Solo cuando los entornos comparten broker. Con un broker por entorno, mantén los topics idénticos en todas partes para promover código y dashboards sin cambios. Si necesitas un prefijo, añádelo en un único lugar del código del cliente.
¿Cómo evito que las pruebas publiquen en producción?
Da las credenciales de producción solo a los servicios de producción, mantenlas fuera de los jobs de prueba de CI y añade una protección en el setup de pruebas que se niegue a ejecutar si el entorno o la URL del broker configurados son los de producción.


