{"id":15001,"date":"2023-01-12T00:00:00","date_gmt":"2023-01-12T00:00:00","guid":{"rendered":"https:\/\/www.mailgun.com\/blog\/reconstruccion-app-mailgun-parte-uno\/"},"modified":"2026-07-24T04:47:33","modified_gmt":"2026-07-24T04:47:33","slug":"reconstruccion-app-mailgun-parte-uno","status":"publish","type":"blog","link":"https:\/\/www.mailgun.com\/es\/blog\/dev-life\/reconstruccion-app-mailgun-parte-uno\/","title":{"rendered":"Un an\u00e1lisis exhaustivo de la reconstrucci\u00f3n de la app de Mailgun: Parte 1 &#8211; Ideas excelentes"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Saludos, compa\u00f1eros desarrolladores. Estamos emocionados de anunciar que, despu\u00e9s de tres largos a\u00f1os de planificaci\u00f3n, dise\u00f1o y desarrollo, nuestro equipo ha lanzado nuestra fant\u00e1stica actualizaci\u00f3n de la app. Claro, hemos trabajado incansablemente para actualizar el aspecto de nuestra interfaz de usuario, pero hemos hecho una revisi\u00f3n a\u00fan m\u00e1s alucinante de <!-- -->nuestro stack tecnol\u00f3gico fundamental<!-- -->.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\u00bfQu\u00e9 significa esto para ti? Mejor rendimiento, mejor interfaz y escalable para el crecimiento futuro. Viajamos atr\u00e1s en el tiempo para traerte el informe completo sobre c\u00f3mo lo logramos. Acomp\u00e1\u00f1anos en el viaje.<\/p>\n\n\n\r\n    <nav data-content-type=\"longform\" class=\"toc-block longform-spacings px-5 py-6 px-md-6 px-lg-7 py-md-7 bg-light fs-sm rounded-lg\" aria-labelledby=\"toc-title-3998\"><p class=\"h5 m-0\" id=\"toc-title-3998\">Table of contents<\/p><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">01<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#por-que-nos-embarcamos-en-este-viaje\">Por qu\u00e9 nos embarcamos en este viaje<\/a><\/div><\/div><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">02<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#lo-que-queriamos-construir\">Lo que quer\u00edamos construir<\/a><\/div><\/div><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">03<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#historia-nuestro-stack-de-front-end-original\">Historia: Nuestro stack de front-end original<\/a><\/div><\/div><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">04<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#como-nuestro-framework-heredado-supuso-un-obstaculo-para-nuestra-escalabilidad\">C\u00f3mo nuestro framework heredado supuso un obst\u00e1culo para nuestra escalabilidad<\/a><a class=\"scrollme link-body-color\" href=\"#el-problema-de-gestionar-los-estados-de-toda-la-app\">El problema de gestionar los estados de toda la app<\/a><\/div><\/div><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">05<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#limitaciones-del-polirepositorio\">Limitaciones del polirepositorio<\/a><\/div><\/div><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">06<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#el-plan-para-un-repositorio-nuevo-y-reluciente-un-enfoque-modular\">El plan para un repositorio nuevo y reluciente: Un enfoque modular<\/a><\/div><\/div><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">07<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#pisando-callos-el-baile-del-despliegue\">Pisando callos: El baile del despliegue<\/a><\/div><\/div><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">08<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#desafios-absurdos-y-soluciones-excelentes\">Desaf\u00edos absurdos y soluciones excelentes<\/a><a class=\"scrollme link-body-color\" href=\"#no-tires-todo-por-la-borda\">No tires todo por la borda<\/a><\/div><\/div><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">09<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#tenemos-un-plan-pero-podemos-hacerlo-realidad\">Tenemos un plan, pero \u00bfpodemos hacerlo realidad?<\/a><\/div><\/div><\/nav>\n\n\n<h2 class=\"wp-block-heading\">Por qu\u00e9 nos embarcamos en este viaje<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\u00a1Pero espera! Antes de viajar atr\u00e1s en el tiempo, es importante presentar nuestra app mejorada. \u00abMejorada\u00bb es quedarse corto. Puede sorprenderte que este lavado de cara de la interfaz de usuario y el rendimiento no fuera un generador de ingresos. Entonces, \u00bfpor qu\u00e9 lo hicimos?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><b>Dos razones:<\/b><\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>La experiencia del usuario, tal como exist\u00eda, inhib\u00eda el rendimiento para los clientes que enviaban grandes vol\u00famenes de emails y dificultaba la navegaci\u00f3n entre los productos de nuestra creciente cartera. Si no es f\u00e1cil de usar, entonces <i>t\u00fa<\/i> no lo usar\u00e1s. <\/li>\n\n\n\n<li>Necesit\u00e1bamos reevaluar el flujo de datos principal de nuestra API para que estuviera m\u00e1s orientado al rendimiento y fuera m\u00e1s escalable.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Lo que hemos creado es el <b>portal<\/b>, una interfaz \u00e9pica para conectarte mejor con tus productos y herramientas de entregabilidad ahora, <i>y<\/i> a medida que escalamos. El <b>portal<\/b> te permite moverte entre nuestro Mailgun y <a href=\"https:\/\/www.mailgun.com\/es\/products\/inbox\/inboxready\/\" target=\"_tabs\" rel=\"noopener noreferrer\">Mailgun Optimize<\/a> productos con facilidad y ofrece una experiencia de alto rendimiento para nuestros usuarios avanzados que env\u00edan decenas de miles de emails al d\u00eda.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">As\u00ed que qu\u00e9date con nosotros mientras nos ponemos frikis, nos sintonizamos y viajamos a trav\u00e9s de los \u00faltimos tres a\u00f1os de nuestro proceso de desarrollo.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" class=\"wp-image-4049\" width=\"1280\" height=\"720\" src=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/bill-teds-excellent-adventure-wallpaper-12__1_.png\" alt=\"bill-teds-excellent-adventure-wallpaper-12__1_\" srcset=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/bill-teds-excellent-adventure-wallpaper-12__1_.png 1280w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/bill-teds-excellent-adventure-wallpaper-12__1_-300x169.png 300w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/bill-teds-excellent-adventure-wallpaper-12__1_-768x432.png 768w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/bill-teds-excellent-adventure-wallpaper-12__1_-1024x576.png 1024w\" sizes=\"(max-width: 1280px) 100vw, 1280px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Lo que quer\u00edamos construir<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Empezamos creando una lista interminable de todas las cosas diferentes que quer\u00edamos: abarcaba desde la actualizaci\u00f3n de la estructura de nuestro repositorio hasta la implementaci\u00f3n de un nuevo sistema de despliegue, y sab\u00edamos que \u00edbamos a tener que crearlo desde cero, ya que nuestro equipo SRE estaba migrando de AWS a Google Cloud. Tambi\u00e9n quer\u00edamos alejarnos de nuestro dise\u00f1o monol\u00edtico estrechamente acoplado y pasar a un dise\u00f1o m\u00e1s distribuido. Esto facilitar\u00eda las cosas para el equipo en el futuro: desde el desarrollo de pruebas exhaustivas hasta la selecci\u00f3n de reconstrucciones sin necesidad de bucear por todo el c\u00f3digo o cambiarlo.<\/p>\n\n\n    <div data-content-type=\"longform\"  class=\"callout text-body-color px-5 py-6 px-md-6 px-lg-7 py-md-7 longform-spacings rounded-lg bg-light\" data-theme=\"light\">\r\n\r\n        <div class=\"content-body\"> \u00bfQu\u00e9 queremos construir a largo plazo? Esta fue la primera pregunta que tuvimos que responder. La siguiente pregunta fue: \u00ab\u00bfEn qu\u00e9 nos quedamos cortos?\u00bb<\/div>\r\n    <\/div>\r\n\n\n\n<p class=\"wp-block-paragraph\"><b>Con cualquier redise\u00f1o, siempre queremos considerar al usuario, pero gran parte del impulso detr\u00e1s de la actualizaci\u00f3n de nuestra app fue tambi\u00e9n mejorar la experiencia del desarrollador. <\/b>Nuestro objetivo era mejorar la experiencia del desarrollador reduciendo significativamente la complejidad de pasar los datos de la API a la p\u00e1gina renderizada, y mejorar la mantenibilidad reduciendo el n\u00famero total de patrones en nuestro conjunto de herramientas.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Historia: Nuestro stack de front-end original<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><b>Los stacks pueden quedarse anticuados, y nuestro stack de front-end original se construy\u00f3 hace casi una d\u00e9cada<\/b>, lo que equivale a 350 en a\u00f1os de internet. Inclu\u00eda un servidor web de Python Flask que probablemente manejaba m\u00e1s tareas de las que deb\u00eda y ten\u00eda un estado muy estrechamente acoplado compartido con el cliente. Usaba m\u00faltiples capas de abstracci\u00f3n, originalmente pensadas para facilitar la obtenci\u00f3n de datos de nuestras API.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A medida que esa superficie crec\u00eda, los patrones aportaban m\u00e1s sobrecarga que comodidad. Se volvi\u00f3 muy dif\u00edcil hacer cambios fundamentales porque hab\u00eda muchos lugares que pod\u00edan verse afectados. Para entonces, nuestro cliente de front-end se hab\u00eda convertido en un museo de patrones obsoletos de React.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Todas nuestras interacciones con nuestras propias API p\u00fablicas y privadas estaban ofuscadas a trav\u00e9s de m\u00faltiples capas de excesivas complejidades de programaci\u00f3n. Esto cre\u00f3 un abismo gigante entre los desarrolladores de front-end de Mailgun y su comprensi\u00f3n de nuestras API y la experiencia del cliente.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">C\u00f3mo nuestro framework heredado supuso un obst\u00e1culo para nuestra escalabilidad<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">La chapuza de abstracciones de la API no solo result\u00f3 en un exceso de complejidad, sino que inhibi\u00f3 significativamente nuestra capacidad para escalar nuestra aplicaci\u00f3n. Sab\u00edamos que quer\u00edamos acabar introduciendo cada vez m\u00e1s productos en la base de c\u00f3digo. Necesitar\u00edamos replantearnos por completo c\u00f3mo consum\u00edamos nuestros datos.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Cuando prepar\u00e1bamos el plan del nuevo framework, sab\u00edamos que quer\u00edamos poder hacer solicitudes de la API directamente desde el cliente a las API p\u00fablicas con la menor cantidad de middleware posible. \u00bfPor qu\u00e9? De esta manera, podr\u00edamos comprender y consumir nuestras API de la misma forma que lo hacen nuestros clientes, \u00abcomiendo nuestra propia comida para perros\u00bb, como suele decirse. No s\u00e9 vosotros, pero yo prefiero comer un filete que comida para perros.<\/p>\n\n\n    <div data-content-type=\"longform\"  class=\"callout text-body-color px-5 py-6 px-md-6 px-lg-7 py-md-7 longform-spacings rounded-lg bg-light\" data-theme=\"light\">\r\n\r\n        <div class=\"content-body\"> <b>Una nota del futuro: <\/b>Hacer solicitudes de API directamente desde el cliente a las API p\u00fablicas es un objetivo a largo plazo, ya que muchas de las API con las que se comunica nuestra aplicaci\u00f3n web siguen siendo privadas. Tenemos un plan para trasladar gradualmente la mayor\u00eda de estos servicios al espacio p\u00fablico y tener una interfaz de API uniforme para el portal.<\/div>\r\n    <\/div>\r\n\n\n\n<h3 class=\"wp-block-heading\">El problema de gestionar los estados de toda la app<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Otro cambio significativo que quer\u00edamos hacer era reemplazar Redux, que gestionaba nuestro estado de toda la app (alrededor de 150 estados). Cada estado se asignaba a una llamada de red, o a una red de transformaciones de datos, y nuestra estructura heredada no establec\u00eda pautas sobre c\u00f3mo usarlo. \u00bfEl resultado? Muchas redundancias.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Cuando un desarrollador introduc\u00eda una llamada para manipular datos, se integraba a trav\u00e9s de tres niveles de abstracci\u00f3n. Adem\u00e1s, ten\u00edamos nuestros propios clientes personalizados para el navegador y para nuestro servidor Flask (que interactuaba con todas nuestras API). Por lo tanto, <b>para que un desarrollador a\u00f1adiera una nueva funci\u00f3n, ten\u00eda que pasar por unos siete niveles de abstracci\u00f3n en total<\/b>, y es posible que haya errores en cualquier nivel.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Lo que finalmente descubrimos fue que el 95 % de nuestro estado a nivel de aplicaci\u00f3n era solo una cach\u00e9 de red glorificada. Solo que ni siquiera est\u00e1bamos cosechando los beneficios de los datos en cach\u00e9, y a menudo hac\u00edamos llamadas redundantes para solicitar datos que ya ten\u00edamos, causando capas anidadas de rerenderizados innecesarios en los componentes de nuestra vista. Vaya viaje tan movido.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Este desglose del sistema explica las cosas con un poco m\u00e1s de claridad, y aunque nunca hablar\u00edamos mal de nuestros or\u00edgenes&#8230; una imagen <i>jocosa<\/i> vale m\u00e1s que mil palabras.<\/p>\n\n\n<div class=\"chart longform-spacings d-flex flex-column gap-3\">\r\n    <div class=\"rounded-lg bg-light-subtle position-relative py-5 py-md-6 py-lg-7 px-3 px-md-4\">\r\n\r\n                    <p class=\"mb-4 fs-sm fw-bold text-accent text-center\">\r\n                Sistema actual            <\/p>\r\n        \r\n                                <div class=\"d-flex gap-4 flex-column\">\r\n                <div class=\"auto-chart\"  data-chart-type=\"bar\" data-chart-percentage=\"true\" data-chart-track=\"true\" data-chart-max=\"100\" data-chart-color=\"#f99b93\" data-chart-values=\"[&quot;61&quot;,&quot;54&quot;,&quot;31&quot;,&quot;88&quot;]\" data-chart-colors=\"[&quot;#FFBE3C&quot;,&quot;#FFBE3C&quot;,&quot;#FFBE3C&quot;,&quot;#FFBE3C&quot;]\" data-chart-titles=\"[&quot;Complejo&quot;,&quot;Lento&quot;,&quot;Tedioso&quot;,&quot;Apesta&quot;]\" data-chart-series=\"[]\"><\/div>\r\n\r\n                            <\/div>\r\n            \r\n        \r\n        \r\n    <\/div>\r\n    <\/div>\n\n\n<p class=\"wp-block-paragraph\">Nuestro equipo es del tipo que construye sobre s\u00ed mismo e itera, pero para la reconstrucci\u00f3n de esta app tuvimos que rebobinar y reelaborar algunos componentes fundamentales de nuestra infraestructura, comenzando por el control del c\u00f3digo fuente.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Limitaciones del polirepositorio<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><b>Un <\/b><a href=\"https:\/\/github.com\/joelparkerhenderson\/monorepo-vs-polyrepo\" target=\"_tabs\" rel=\"noopener noreferrer\"><b>polirepositorio<\/b><\/a><b> es un repositorio que contiene m\u00faltiples proyectos. <\/b>Us\u00e1bamos un estilo de organizaci\u00f3n de polirepositorio, lo que significa que cada proyecto de front-end ten\u00eda su propio repositorio, aunque muchos de los proyectos repet\u00edan las mismas tareas y reproduc\u00edan las mismas funciones. Como centro principal, los polirepositorios pueden convertirse en un desaf\u00edo de mantenimiento a medida que crece el n\u00famero de proyectos almacenados. En muchos casos, tuvimos que desplegar cada polirepositorio simult\u00e1neamente con las mismas actualizaciones para asegurar una experiencia coherente en todos nuestros productos.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Desde la perspectiva del mantenimiento, esto dificultaba que los equipos localizaran y trabajaran con el c\u00f3digo que necesitaban. Gestionar m\u00faltiples repositorios con caracter\u00edsticas redundantes suele significar que son m\u00e1s lentos en responder <i>y<\/i> que consumen m\u00e1s recursos, lo cual es un gran problema si frecuentemente haces push y pull de c\u00f3digo. Como las funciones pueden distribuirse en m\u00faltiples bases de c\u00f3digo, los polirepositorios pueden hacer que encontrar errores sea m\u00e1s dif\u00edcil que encontrar la proverbial aguja en el pajar.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Con nuestra estructura de polirepositorio previa a la reconstrucci\u00f3n, sab\u00edamos que el futuro ser\u00eda una realidad de buscar en los repositorios con una linterna para encontrar lo que necesit\u00e1bamos, y que ser\u00eda un desaf\u00edo colaborar, escalar y compartir c\u00f3digo a medida que crec\u00edamos.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><b>Estas eran nuestras principales preocupaciones:<\/b><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Codesarrollo desafiante<\/li>\n\n\n\n<li>Acoplamiento estrecho<\/li>\n\n\n\n<li>Gesti\u00f3n de la escalabilidad, disponibilidad y rendimiento<\/li>\n\n\n\n<li>Dificultad para compartir c\u00f3digo<\/li>\n\n\n\n<li>Duplicaci\u00f3n<\/li>\n\n\n\n<li>Herramientas inconsistentes<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">En cuanto a la gesti\u00f3n del c\u00f3digo fuente, hay muchas soluciones, pero decidimos que una estructura modular de monorepositorio aliviar\u00eda la mayor\u00eda de nuestros problemas de desarrollo de cara al futuro.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">El plan para un repositorio nuevo y reluciente: Un enfoque modular<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><b>Un enfoque de monorepositorio implica almacenar todo el c\u00f3digo del proyecto en un solo repositorio grande<\/b>. Esto resolver\u00eda los problemas de duplicaci\u00f3n y compartici\u00f3n de c\u00f3digo que experimentamos con nuestra organizaci\u00f3n de polirepositorio, pero los monorepositorios no son una soluci\u00f3n m\u00e1gica. Si el c\u00f3digo est\u00e1 estrechamente acoplado, los monorepositorios tambi\u00e9n deben dise\u00f1arse de forma modular.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><b>Un enfoque modular implica dividir un proyecto grande en m\u00f3dulos m\u00e1s peque\u00f1os e independientes que se pueden desarrollar, probar y mantener por separado<\/b>. Esto permite una mayor flexibilidad y reutilizaci\u00f3n, as\u00ed como la capacidad de actualizar f\u00e1cilmente los m\u00f3dulos individuales sin afectar al resto del proyecto.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Sab\u00edamos que una soluci\u00f3n modular de monorepositorio nos permitir\u00eda ser m\u00e1s eficientes con:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Generaci\u00f3n de c\u00f3digo<\/li>\n\n\n\n<li>Compartir c\u00f3digo<\/li>\n\n\n\n<li>Ejecuci\u00f3n y orquestaci\u00f3n distribuida de tareas<\/li>\n\n\n\n<li>Cach\u00e9<\/li>\n\n\n\n<li>TypeScript<\/li>\n<\/ul>\n\n\n    <div data-content-type=\"longform\"  class=\"callout text-body-color px-5 py-6 px-md-6 px-lg-7 py-md-7 longform-spacings rounded-lg bg-light\" data-theme=\"light\">\r\n\r\n        <div class=\"content-body\"> <b>TypeScript es un superconjunto tipado de JavaScript que facilita a los desarrolladores la creaci\u00f3n de proyectos a gran escala.<\/b> Mejora la experiencia del desarrollador al proporcionar interfaces, alias de tipo, an\u00e1lisis de c\u00f3digo est\u00e1tico en tiempo de desarrollo y otras herramientas, a la vez que permite a los desarrolladores a\u00f1adir tipado a sus proyectos. Para nuestro equipo, TypeScript es una habilidad que sab\u00edamos que quer\u00edamos empezar a buscar a la hora de a\u00f1adir miembros a nuestro equipo.<\/div>\r\n    <\/div>\r\n\n\n\n<h2 class=\"wp-block-heading\">Pisando callos: El baile del despliegue<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Sin lugar a duda, el mayor desaf\u00edo de vivir en un monorepositorio (monol\u00edtico o no) es que cuantas m\u00e1s personas contribuyan, mayor ser\u00e1 la posibilidad de que nos pisemos los unos a los otros. \u00bfDe qu\u00e9 sirve una experiencia de desarrollo renovada si tu c\u00f3digo se sobrescribe en una mala fusi\u00f3n? Si realmente estamos haciendo una revisi\u00f3n integral de nuestro stack, tambi\u00e9n debemos estudiar c\u00f3mo podemos mejorar nuestro proceso de despliegue. Estos eran los retos m\u00e1s urgentes:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><b>Escalabilidad: <\/b>Ser\u00eda una mala idea reconstruir TODO el c\u00f3digo del monorepositorio para los cambios m\u00e1s peque\u00f1os, por ejemplo, corregir un error tipogr\u00e1fico en alg\u00fan texto. Eso es exactamente lo que hac\u00edamos en nuestro antiguo sistema. El nuevo proceso aprovechar\u00eda las capacidades integradas de NX para evaluar y reconstruir \u00fanicamente el archivo o archivos afectados por el cambio, en el nivel m\u00e1s granular.<\/li>\n\n\n\n<li><b>Despliegue: <\/b>Mantuvimos la mayor parte de la estructura de nuestra canalizaci\u00f3n de despliegue. Una vez construida la imagen, aterriza en el repositorio de contenedores de GitHub. Nuestro equipo SRE puso a punto nuestro sistema de despliegue durante la migraci\u00f3n de AWS a GCP. Podemos desplegar f\u00e1cilmente cualquier rama desde nuestro canal de despliegue de Slack, con un mejor informe gracias a una incorporaci\u00f3n reciente que obtuvimos durante la migraci\u00f3n.<\/li>\n\n\n\n<li><b>CI\/CD:<\/b> Nuestro antiguo sistema usaba una versi\u00f3n muy antigua de Jenkins para ejecutar pruebas y construir\/distribuir las im\u00e1genes de nuestra app tras una VPN. Cuando la compilaci\u00f3n fallaba, necesit\u00e1bamos que un desarrollador s\u00e9nior de alto nivel, familiarizado con las viejas costumbres, lo arreglara. En nuestro nuevo sistema, el plan era pasarnos a GitHub Actions, donde las configuraciones son accesibles, declarativas y est\u00e1n bien documentadas.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Desaf\u00edos absurdos y soluciones excelentes<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Los proyectos de cualquier tipo presentan desaf\u00edos, algunos esperados y otros sorprendentes. Sab\u00edamos que necesit\u00e1bamos un plan para superar algunos problemas y que la nueva versi\u00f3n de la app deb\u00eda centrarse en el rendimiento desde m\u00faltiples \u00e1ngulos.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Problemas identificados<\/th><th>Soluciones propuestas<\/th><\/tr><\/thead><tbody><tr><td><strong>Convenciones de c\u00f3digo poco claras<\/strong><br>Las convenciones de c\u00f3digo se refieren al conjunto de estilos de programaci\u00f3n, soluciones y patrones reutilizables dentro de una base de c\u00f3digo. Imagina un equipo de carpinteros trabajando en un proyecto. Si tienen 1000 herramientas especializadas en el lugar de trabajo, es probable que un trabajador elija la herramienta equivocada para el trabajo o la use de forma incorrecta. Y a diferencia de las herramientas f\u00edsicas, las dependencias de software pueden quedar obsoletas, lo que inhibe las futuras actualizaciones de la base de c\u00f3digo.<\/td><td><strong>Gu\u00eda de estilo de c\u00f3digo<\/strong><br>Mantener gu\u00edas expl\u00edcitas de estilo de programaci\u00f3n\u00a0y un conjunto m\u00ednimo de patrones simples y potentes ayuda a reducir la redundancia, las inconsistencias y la complejidad, e incluso puede resultar en un mejor rendimiento. Reutilizar un peque\u00f1o conjunto de soluciones y patrones generalizados hace que el c\u00f3digo sea m\u00e1s f\u00e1cil de entender y reduce la probabilidad de encontrar errores dif\u00edciles de localizar.<\/td><\/tr><tr><td><strong>Estado sobrecargado<\/strong><br>Us\u00e1bamos Redux como una soluci\u00f3n universal para el estado global de la aplicaci\u00f3n. Sin embargo, el 90 % de nuestro almacenamiento Redux no era m\u00e1s que una cach\u00e9 de red glorificada. Redux requiere m\u00faltiples capas de sobrecarga para cada miembro del estado. Esto dio lugar a muchas redundancias y una complejidad innecesaria.<\/td><td><strong>Separaci\u00f3n de la cach\u00e9 de red y el estado de la aplicaci\u00f3n<\/strong><br>Separar las caracter\u00edsticas de la cach\u00e9 de red del estado de la aplicaci\u00f3n nos permite mantener una huella de estado mucho menor. El estado se puede implementar de forma m\u00e1s local. La reducci\u00f3n de la sobrecarga se traduce en un aumento del rendimiento y da a los desarrolladores m\u00e1s control sobre c\u00f3mo se utilizan los datos.<br>Elegimos React Query\u00a0como interfaz para las API de nuestro backend, lo que nos permite gestionar los datos de forma as\u00edncrona y reducir la sobrecarga de la red.<\/td><\/tr><tr><td><strong>Arquitectura de red multicapa<\/strong><br>Nuestra aplicaci\u00f3n creci\u00f3 de forma org\u00e1nica, desde un panel de control b\u00e1sico centrado en la API hasta la suite multiproducto de herramientas para el cliente que tenemos hoy. Inicialmente, el cliente se construy\u00f3 sobre unas herramientas comunes de Python compartidas por muchos de los backends de nuestras API. Esto lleva a tener numerosas capas de middleware necesarias incluso para la llamada a la API m\u00e1s sencilla. Esto no solo dificultaba entender el origen de un dato dado, sino que tambi\u00e9n hac\u00eda que la identificaci\u00f3n de errores en el stack de red llevara mucho tiempo.<\/td><td><strong>Las API p\u00fablicas primero<\/strong><br>En lugar de pasar las solicitudes por m\u00faltiples proxies, capas de autenticaci\u00f3n e interfaces de Python, decidimos desde el principio que, siempre que fuera posible, recopilar\u00edamos los datos necesarios directamente desde el cliente utilizando las API disponibles p\u00fablicamente. Esto no solo redujo significativamente nuestra sobrecarga y complejidad, sino que nos ayud\u00f3 a percibir mejor nuestros servicios de API desde la perspectiva de nuestros clientes. Tenemos la intenci\u00f3n de llevar esta iniciativa m\u00e1s all\u00e1 en el futuro cercano, haciendo p\u00fablicas m\u00e1s API nuestras.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">No tires todo por la borda<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Hemos escrito cientos de miles de l\u00edneas de c\u00f3digo durante la \u00faltima d\u00e9cada. Con la escala y el alcance de este nuevo plan, se tardar\u00eda casi los mismos a\u00f1os en portar y reescribir nuestras funciones antiguas en el nuevo paradigma. Esto era inasumible. Necesit\u00e1bamos encontrar una forma de seguir incorporando estas funciones existentes sin comprometer nuestros objetivos para el nuevo stack. Encontramos una soluci\u00f3n en una tecnolog\u00eda llamada federaci\u00f3n de m\u00f3dulos.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Con el plugin de federaci\u00f3n de m\u00f3dulos de Webpack, pudimos <b>crear una nueva compilaci\u00f3n de nuestra antigua aplicaci\u00f3n con cambios m\u00ednimos<\/b>, que podr\u00eda integrar las funciones existentes en el nuevo stack del portal. Seguir\u00edamos teniendo el objetivo a largo plazo de portar el c\u00f3digo ahora heredado a est\u00e1ndares m\u00e1s nuevos, pero esto nos permitir\u00eda empezar a escribir nuevas funciones con los nuevos beneficios inmediatamente.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Tenemos un plan, pero \u00bfpodemos hacerlo realidad?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Sab\u00edamos que consolidar nuestras plataformas mientras segu\u00edamos aumentando las funciones y los conjuntos de productos requerir\u00eda un esfuerzo masivo, y nuestra planificaci\u00f3n influy\u00f3 en lo que quer\u00edamos para nuestro nuevo stack de front-end y en c\u00f3mo \u00edbamos a gestionar el interminable legado de los sistemas de estilos CSS anticuados, los patrones de componentes de clase obsoletos y la torpe gesti\u00f3n del estado de la aplicaci\u00f3n.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Como lo est\u00e1bamos construyendo desde cero, especialmente con el paso de AWS a Google Cloud, <b>la mejor soluci\u00f3n era hacer borr\u00f3n y cuenta nueva<\/b>. Un nuevo repositorio con mejores y m\u00e1s altos est\u00e1ndares, federaci\u00f3n de m\u00f3dulos, bibliotecas modulares compartidas y una documentaci\u00f3n m\u00e1s completa a nivel interno y orientada al usuario.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" class=\"wp-image-4052\" width=\"1440\" height=\"748\" src=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/EN-Tools-Trade.png\" alt=\"New front-end stack; Nx, React, Webpack, TypeScript, Cypress, Jest, ES Links, Prettier, and Mock Service Worker.\" srcset=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/EN-Tools-Trade.png 1440w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/EN-Tools-Trade-300x156.png 300w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/EN-Tools-Trade-768x399.png 768w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/EN-Tools-Trade-1024x532.png 1024w\" sizes=\"(max-width: 1440px) 100vw, 1440px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Fue una etapa intensa de planificaci\u00f3n y preparaci\u00f3n. Como en todos los grandes proyectos, generar las ideas y la prueba de concepto fue un esfuerzo t\u00e9cnico y creativo en el que solo participaron unas pocas personas seleccionadas.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\u00bfFase 2? Convertir la idea en realidad, y eso implicaba a muchos m\u00e1s equipos. Desarrolladores, creo que nuestra aventura est\u00e1 a punto de dar un giro muy interesante. <\/p>\n\n\n\r\n    <aside data-content-type=\"longform\"  class=\"banner-block longform-spacings rounded-lg shadow-lg px-5 py-6 px-md-6 py-md-7 p-lg-7 bg-light\" data-theme=\"dark\" aria-labelledby=\"banner-block-block_c02b5b2d19c630fe3cea806f69135f94\">\r\n                            <p class=\"h4 text-accent fw-bold\" id=\"banner-block-block_c02b5b2d19c630fe3cea806f69135f94\">\r\n                Echa un vistazo a la Parte 2: Una ejecuci\u00f3n triunfal            <\/p>\r\n                            <div class=\"mb-0 text-body-color\">\r\n                                    <div class=\"content-body mb-0 text-body-color\">En la parte 1 respondimos a la pregunta: \u00bfPor qu\u00e9 reconstruir? En la parte 2, nos sumergiremos en la implementaci\u00f3n y ejecuci\u00f3n. Tiene drama, tiene migraciones&#8230; y probablemente demasiadas referencias de ciencia ficci\u00f3n. Acomp\u00e1\u00f1anos en el viaje.<\/div>\r\n                            <\/div>\r\n        \r\n        <div class=\"text-start mt-5\"><a href=\"https:\/\/www.mailgun.com\/blog\/dev-life\/mailgun-app-rebuild-part-two\/\"  class=\"btn btn-secondary\" >Read the blog<\/a><\/div>\r\n    <\/aside>\r\n\r\n","protected":false},"excerpt":{"rendered":"<p>Saludos, compa\u00f1eros desarrolladores. Estamos emocionados de anunciar que, despu\u00e9s de tres largos a\u00f1os de planificaci\u00f3n, dise\u00f1o y desarrollo, nuestro equipo ha lanzado nuestra fant\u00e1stica actualizaci\u00f3n de la app. Claro, hemos trabajado incansablemente para actualizar el aspecto de nuestra interfaz de usuario, pero hemos hecho una revisi\u00f3n a\u00fan m\u00e1s alucinante de nuestro stack tecnol\u00f3gico fundamental. \u00bfQu\u00e9 [&hellip;]<\/p>\n","protected":false},"author":17,"featured_media":3952,"menu_order":0,"template":"","meta":{"_acf_changed":false,"footnotes":""},"blog_category":[19],"class_list":["post-15001","blog","type-blog","status-publish","has-post-thumbnail","hentry","blog_category-dev-life"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>C\u00f3mo reconstruimos nuestra app de Mailgun para varios productos: Parte 1 - Transactional Email API Service For Developers | Mailgun<\/title>\n<meta name=\"description\" content=\"La actualizaci\u00f3n de la app de Mailgun reci\u00e9n lanzada empez\u00f3 como una iniciativa de base. \u00bfQuieres ver c\u00f3mo lo logramos? \u00danete a nosotros en esta excelente aventura.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.mailgun.com\/es\/blog\/dev-life\/reconstruccion-app-mailgun-parte-uno\/\" \/>\n<meta property=\"og:locale\" content=\"es_ES\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"C\u00f3mo reconstruimos nuestra app de Mailgun para varios productos: Parte 1 - Transactional Email API Service For Developers | Mailgun\" \/>\n<meta property=\"og:description\" content=\"La actualizaci\u00f3n de la app de Mailgun reci\u00e9n lanzada empez\u00f3 como una iniciativa de base. \u00bfQuieres ver c\u00f3mo lo logramos? \u00danete a nosotros en esta excelente aventura.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.mailgun.com\/es\/blog\/dev-life\/reconstruccion-app-mailgun-parte-uno\/\" \/>\n<meta property=\"og:site_name\" content=\"Transactional Email API Service For Developers | Mailgun\" \/>\n<meta property=\"article:modified_time\" content=\"2026-07-24T04:47:33+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/MG-Blog-Dev-Life.png\" \/>\n\t<meta property=\"og:image:width\" content=\"720\" \/>\n\t<meta property=\"og:image:height\" content=\"448\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"11 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/blog\\\/dev-life\\\/reconstruccion-app-mailgun-parte-uno\\\/\",\"url\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/blog\\\/dev-life\\\/reconstruccion-app-mailgun-parte-uno\\\/\",\"name\":\"C\u00f3mo reconstruimos nuestra app de Mailgun para varios productos: Parte 1 - Transactional Email API Service For Developers | Mailgun\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/blog\\\/dev-life\\\/reconstruccion-app-mailgun-parte-uno\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/blog\\\/dev-life\\\/reconstruccion-app-mailgun-parte-uno\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.mailgun.com\\\/wp-content\\\/uploads\\\/2025\\\/07\\\/MG-Blog-Dev-Life.png\",\"datePublished\":\"2023-01-12T00:00:00+00:00\",\"dateModified\":\"2026-07-24T04:47:33+00:00\",\"description\":\"La actualizaci\u00f3n de la app de Mailgun reci\u00e9n lanzada empez\u00f3 como una iniciativa de base. \u00bfQuieres ver c\u00f3mo lo logramos? \u00danete a nosotros en esta excelente aventura.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/blog\\\/dev-life\\\/reconstruccion-app-mailgun-parte-uno\\\/#breadcrumb\"},\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.mailgun.com\\\/es\\\/blog\\\/dev-life\\\/reconstruccion-app-mailgun-parte-uno\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/blog\\\/dev-life\\\/reconstruccion-app-mailgun-parte-uno\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.mailgun.com\\\/wp-content\\\/uploads\\\/2025\\\/07\\\/MG-Blog-Dev-Life.png\",\"contentUrl\":\"https:\\\/\\\/www.mailgun.com\\\/wp-content\\\/uploads\\\/2025\\\/07\\\/MG-Blog-Dev-Life.png\",\"width\":720,\"height\":448},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/blog\\\/dev-life\\\/reconstruccion-app-mailgun-parte-uno\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Blog\",\"item\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Un an\u00e1lisis exhaustivo de la reconstrucci\u00f3n de la app de Mailgun: Parte 1 \u2013 Ideas excelentes\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/#website\",\"url\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/\",\"name\":\"Transactional Email API Service For Developers | Mailgun\",\"description\":\"Powerful Transactional Email APIs that enable you to send, receive, and track emails, built with developers in mind. Learn more today!\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"es\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/#organization\",\"name\":\"Transactional Email API Service For Developers | Mailgun\",\"url\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.mailgun.com\\\/wp-content\\\/uploads\\\/2025\\\/06\\\/cropped-android-chrome-512x512-1.png\",\"contentUrl\":\"https:\\\/\\\/www.mailgun.com\\\/wp-content\\\/uploads\\\/2025\\\/06\\\/cropped-android-chrome-512x512-1.png\",\"width\":512,\"height\":512,\"caption\":\"Transactional Email API Service For Developers | Mailgun\"},\"image\":{\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/#\\\/schema\\\/logo\\\/image\\\/\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"C\u00f3mo reconstruimos nuestra app de Mailgun para varios productos: Parte 1 - Transactional Email API Service For Developers | Mailgun","description":"La actualizaci\u00f3n de la app de Mailgun reci\u00e9n lanzada empez\u00f3 como una iniciativa de base. \u00bfQuieres ver c\u00f3mo lo logramos? \u00danete a nosotros en esta excelente aventura.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.mailgun.com\/es\/blog\/dev-life\/reconstruccion-app-mailgun-parte-uno\/","og_locale":"es_ES","og_type":"article","og_title":"C\u00f3mo reconstruimos nuestra app de Mailgun para varios productos: Parte 1 - Transactional Email API Service For Developers | Mailgun","og_description":"La actualizaci\u00f3n de la app de Mailgun reci\u00e9n lanzada empez\u00f3 como una iniciativa de base. \u00bfQuieres ver c\u00f3mo lo logramos? \u00danete a nosotros en esta excelente aventura.","og_url":"https:\/\/www.mailgun.com\/es\/blog\/dev-life\/reconstruccion-app-mailgun-parte-uno\/","og_site_name":"Transactional Email API Service For Developers | Mailgun","article_modified_time":"2026-07-24T04:47:33+00:00","og_image":[{"width":720,"height":448,"url":"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/MG-Blog-Dev-Life.png","type":"image\/png"}],"twitter_card":"summary_large_image","twitter_misc":{"Est. reading time":"11 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.mailgun.com\/es\/blog\/dev-life\/reconstruccion-app-mailgun-parte-uno\/","url":"https:\/\/www.mailgun.com\/es\/blog\/dev-life\/reconstruccion-app-mailgun-parte-uno\/","name":"C\u00f3mo reconstruimos nuestra app de Mailgun para varios productos: Parte 1 - Transactional Email API Service For Developers | Mailgun","isPartOf":{"@id":"https:\/\/www.mailgun.com\/es\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.mailgun.com\/es\/blog\/dev-life\/reconstruccion-app-mailgun-parte-uno\/#primaryimage"},"image":{"@id":"https:\/\/www.mailgun.com\/es\/blog\/dev-life\/reconstruccion-app-mailgun-parte-uno\/#primaryimage"},"thumbnailUrl":"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/MG-Blog-Dev-Life.png","datePublished":"2023-01-12T00:00:00+00:00","dateModified":"2026-07-24T04:47:33+00:00","description":"La actualizaci\u00f3n de la app de Mailgun reci\u00e9n lanzada empez\u00f3 como una iniciativa de base. \u00bfQuieres ver c\u00f3mo lo logramos? \u00danete a nosotros en esta excelente aventura.","breadcrumb":{"@id":"https:\/\/www.mailgun.com\/es\/blog\/dev-life\/reconstruccion-app-mailgun-parte-uno\/#breadcrumb"},"inLanguage":"es","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.mailgun.com\/es\/blog\/dev-life\/reconstruccion-app-mailgun-parte-uno\/"]}]},{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/www.mailgun.com\/es\/blog\/dev-life\/reconstruccion-app-mailgun-parte-uno\/#primaryimage","url":"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/MG-Blog-Dev-Life.png","contentUrl":"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/MG-Blog-Dev-Life.png","width":720,"height":448},{"@type":"BreadcrumbList","@id":"https:\/\/www.mailgun.com\/es\/blog\/dev-life\/reconstruccion-app-mailgun-parte-uno\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.mailgun.com\/es\/"},{"@type":"ListItem","position":2,"name":"Blog","item":"https:\/\/www.mailgun.com\/es\/blog\/"},{"@type":"ListItem","position":3,"name":"Un an\u00e1lisis exhaustivo de la reconstrucci\u00f3n de la app de Mailgun: Parte 1 \u2013 Ideas excelentes"}]},{"@type":"WebSite","@id":"https:\/\/www.mailgun.com\/es\/#website","url":"https:\/\/www.mailgun.com\/es\/","name":"Transactional Email API Service For Developers | Mailgun","description":"Powerful Transactional Email APIs that enable you to send, receive, and track emails, built with developers in mind. Learn more today!","publisher":{"@id":"https:\/\/www.mailgun.com\/es\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.mailgun.com\/es\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"es"},{"@type":"Organization","@id":"https:\/\/www.mailgun.com\/es\/#organization","name":"Transactional Email API Service For Developers | Mailgun","url":"https:\/\/www.mailgun.com\/es\/","logo":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/www.mailgun.com\/es\/#\/schema\/logo\/image\/","url":"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/06\/cropped-android-chrome-512x512-1.png","contentUrl":"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/06\/cropped-android-chrome-512x512-1.png","width":512,"height":512,"caption":"Transactional Email API Service For Developers | Mailgun"},"image":{"@id":"https:\/\/www.mailgun.com\/es\/#\/schema\/logo\/image\/"}}]}},"_links":{"self":[{"href":"https:\/\/www.mailgun.com\/es\/wp-json\/wp\/v2\/blog\/15001","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.mailgun.com\/es\/wp-json\/wp\/v2\/blog"}],"about":[{"href":"https:\/\/www.mailgun.com\/es\/wp-json\/wp\/v2\/types\/blog"}],"author":[{"embeddable":true,"href":"https:\/\/www.mailgun.com\/es\/wp-json\/wp\/v2\/users\/17"}],"version-history":[{"count":2,"href":"https:\/\/www.mailgun.com\/es\/wp-json\/wp\/v2\/blog\/15001\/revisions"}],"predecessor-version":[{"id":15096,"href":"https:\/\/www.mailgun.com\/es\/wp-json\/wp\/v2\/blog\/15001\/revisions\/15096"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.mailgun.com\/es\/wp-json\/wp\/v2\/media\/3952"}],"wp:attachment":[{"href":"https:\/\/www.mailgun.com\/es\/wp-json\/wp\/v2\/media?parent=15001"}],"wp:term":[{"taxonomy":"blog_category","embeddable":true,"href":"https:\/\/www.mailgun.com\/es\/wp-json\/wp\/v2\/blog_category?post=15001"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}