Desplegar Django amb Kamal a servidors propis
31/03/2026
La vostra aplicació Django funciona en local, passa els tests i l'equip vol portar-la a producció. Però entre “funciona a la meva màquina” i “corre de manera estable en un servidor” hi ha un territori ple de decisions que poques vegades s'expliquen bé. Kamal encaixa justament en aquest espai intermedi: quan els scripts manuals ja no escalen, però Kubernetes segueix sent més del que necessites.
Tens un projecte Django que ja ha deixat enrere la fase de prototip, amb usuaris reals oa punt de tenir-ne, i cada nova versió segueix depenent d'una seqüència de passos que només una persona de l'equip domina des del principi fins al final. Algú entra per SSH al servidor, fa un pull, reinicia el servei, comprova que la web carrega i espera que res no s'hagi trencat pel camí.
Aquest model pot funcionar durant un temps. El problema no és que el desplegament manual sigui impossible, sinó que és difícil repetir amb seguretat. Quan un pas canvia i no queda documentat, el procés es torna una mica més fràgil. Quan l'equip creix, aquesta fragilitat acumulada es comença a convertir en risc real: desplegaments fallits, temps d'inactivitat innecessari i la sensació generalitzada que tot se sosté amb filferro.
Kamal apareix com a resposta a aquest escenari concret. No com una plataforma d'orquestració, ni com a substitut de la infraestructura que ja tens, sinó com una forma d'estandarditzar com es construeix, publica i actualitza la teva aplicació a servidors que controles directament.
Què és Kamal i quin problema resol en desplegar Django
Kamal és una eina de desplegament per a aplicacions empaquetades en contenidors. No crea infraestructura ni dissenya la teva arquitectura: introdueix un procés repetible per publicar noves versions a màquines que ja tens i administres. Desenvolupada per l'equip de 37signals , va néixer d'una necessitat molt concreta: desplegar aplicacions web en servidors propis sense dependre de plataformes gestionades ni muntar un clúster de Kubernetes, perquè entre tots dos extrems hi havia un buit on la majoria d'equips petits i mitjans es movien amb scripts artesanals que funcionaven fins que deixaven de fer-ho.
El valor real de Kamal està en la disciplina operativa que introdueix en el cicle de desplegament: construir la imatge, publicar-la en un registre, desplegar-la als servidors de destinació i coordinar els serveis relacionats amb un flux predictible que es repeteix de la mateixa manera en cada nova versió sense necessitat de recordar passos manuals intermedis.
Per a projectes Django desplegats en servidors propis o VPS, aquest encaix resulta especialment natural perquè la majoria d'aplicacions Django comparteixen una arquitectura reconeixible: un servei web que atén peticions HTTP, un o diversos workers que processen tasques asíncrones en segon pla, una base de dades PostgreSQL, una capa de memòria cau amb Redis i un prox. Kamal sap coordinar totes aquestes peces sense obligar-te a adoptar una plataforma molt més gran de la que realment necessites, cosa que el converteix en una opció molt raonable per a aquest punt intermedi on els scripts manuals ja no donen confiança suficient però Kubernetes representaria un salt de complexitat desproporcionat.
El que Kamal no és. Convé deixar-ho clar des del principi per evitar expectatives errònies: Kamal no substitueix Docker, ni el proxy invers, ni PostgreSQL, ni el teu proveïdor d'infraestructura. No dissenya l'arquitectura de la teva aplicació, no converteix una aplicació mal preparada per a producció en una aplicació robusta i no elimina la necessitat de prendre decisions sobre còpies de seguretat, seguretat, observabilitat o persistència de dades. Presentar-ho com a "la teva pròpia PaaS" seria enganyós perquè en realitat és una eina de desplegament i coordinació de contenidors, no una plataforma completa que cobreixi tot el cicle operatiu d'una aplicació en producció.
Quan té sentit fer servir Kamal per desplegar Django
No tots els projectes necessiten Kamal, i reconèixer si el teu encaixa abans d'invertir temps en configurar-lo et pot estalviar força problemes a mitjà termini. El criteri de fons és relativament simple: Kamal és útil quan vols estandarditzar els teus desplegaments sense assumir la complexitat d'una plataforma d'orquestració més gran, i encaixa pitjor quan el teu sistema ja ha crescut fins a un punt que necessita capacitats que van més enllà de coordinar contenidors sobre servidors coneguts.
On encaixa
El perfil més habitual és el d'equips petits o mitjans que mantenen control sobre els seus servidors —per cost, simplicitat operativa o preferència per una infraestructura comprensible— i treballen en projectes amb arquitectura moderada: una aplicació Django com a servei principal, un o més workers, base de dades i memòria cau. Encaixa especialment bé en productes amb un ritme de canvis regular, on importa desplegar de manera ordenada i amb confiança, sense necessitat de canviar de proveïdor, migrar a una plataforma gestionada ni muntar infraestructura addicional que després cal mantenir.
On encaixa pitjor
Els límits apareixen en sistemes amb arquitectures complexes: molts serveis independents, escalat desigual, necessitats avançades de xarxa, desplegaments multiregió o requisits estrictes d'aïllament entre serveis. També encaixa pitjor en organitzacions que ja depenen d?una plataforma gestionada i no volen assumir l?operació directa de servidors.
I convé dir-ho amb claredat: si al teu equip ningú no pot o vol ocupar-se d'operar servidors —seguretat, backups, recuperació davant errors, actualitzacions del sistema i manteniment general—, Kamal no resol aquest problema. Simplifica el desplegament, però no externalitza la responsabilitat de producció. En aquests casos, una plataforma gestionada pot tenir més sentit.
"Arquitectura simple" no vol dir projecte petit ni poc seriós, sinó que el model de "contenidor més servidor més desplegament coordinat" segueix sent suficient per representar el teu sistema real.
Les peces necessàries abans de tocar la configuració
Abans d'obrir cap fitxer de configuració de Kamal, convé tenir clar quines peces componen el teu sistema, quina responsabilitat té cadascuna i quines relacions hi ha entre elles. Saltar aquest pas és una causa freqüent de desplegaments que semblen funcionar al principi però es trenquen després del primer reinici o redeploy.
L'aplicació Django és el centre del sistema perquè serveix les peticions web, concentra la lògica de negoci i depèn de configuració, secrets i serveis externs per funcionar correctament, però no és l'única peça que necessita atenció durant el desplegament ni la més difícil de gestionar.
El servidor intermediari rep el trànsit que arriba al domini públic, acaba la connexió TLS si escau i reenvia les peticions al servei web de l'aplicació. Kamal pot gestionar aquesta capa però necessita que el domini, el DNS i la configuració de xarxa ja estiguin correctament plantejats abans que el desplegament els requereixi, perquè la capa d'accés públic no apareix per art de màgia només per fer servir una eina de desplegament.
Els workers processen tasques asíncrones quan el projecte utilitza cues de treball, ja sigui amb Celery, Django-RQ o una altra solució similar. És important entendre que els workers són processos completament diferents del servei web encara que acostumin a compartir la mateixa imatge de contenidor i la mateixa base de codi: tenen el seu propi perfil de consum de recursos, el seu propi ritme d'execució i les necessitats de configuració pròpies. Si la vostra aplicació processa pagaments en segon pla, envia correus electrònics, genera informes o executa qualsevol tipus de tasca diferida, els workers no són un complement opcional sinó una part essencial del desplegament, i publicar només la part web assumint que allò asíncron "ja funcionarà" és una font d'incidents molt més freqüent del que sembla.
La base de dades té el seu propi cicle de vida, la seva pròpia estratègia de còpies de seguretat i les seves pròpies necessitats de persistència i recuperació que no haurien de tractar-se com un detall més dins del contenidor de l'aplicació. El mateix aplica a la memòria cau : Redis apareix sovint en projectes Django per gestionar cues, sessions, bloquejos distribuïts o simplement per millorar el rendiment de consultes repetides, i en tots els casos necessita una decisió deliberada i conscient sobre on s'executa, com es persisteixen les dades si cal i què passa quan el servei es reinicia.
Els fitxers persistents —mitjana uploads pujats per usuaris, actius generats per l'aplicació o qualsevol contingut que hagi de sobreviure al cicle de vida del contenidor— mereixen atenció especial perquè si el contenidor es reemplaça a cada desplegament (que és exactament el que passa quan fas servir Kamal), qualsevol fitxer emmagatzemat dins seu desapareix amb la versió anterior sense possibilitat de recuperar-lo.
La relació entre totes aquestes peces també importa per al desplegament. El servei web atén trànsit i consulta la base de dades i la memòria cau segons la lògica de l'aplicació; els workers consumeixen tasques des de la cua i generalment depenen de la mateixa configuració base que la part web; la base de dades i la memòria cau són dependències d'infraestructura amb cicles de vida propis, no components efímers que apareixen i desapareixen amb cada release; i el proxy exposa una interfície pública estable encara que la versió interna de l'aplicació canviï amb cada desplegament.
La distinció fonamental és aquesta: Kamal desplega i coordina contenidors d'aplicació, però no resol el disseny de la base de dades, els backups, la persistència, l'estratègia de mitges i fitxers ni la seguretat de xarxa. Confondre eina de desplegament amb arquitectura de producció és un dels errors més habituals.
Preparar l'aplicació abans del primer desplegament
El desplegament correcte comença molt abans de la primera ordre, i la majoria de tutorials i guies ràpides cometen l'error de saltar directament a la configuració de Kamal deixant implícita tota la feina de preparació prèvia, que és precisament on es concentren els errors més difícils de diagnosticar en producció perquè no apareixen de forma òbvia ni generen missatges d'error clars.
L'aplicació Django ha d'estar preparada per a la producció. No n'hi ha prou que el Dockerfile arrenqui. Necessites configuració separada de l'entorn local, ALLOWED_HOSTS correcte, DEBUG desactivat, HTTPS i galetes segures, estratègia clara per a collectstatic, logging útil i algun health check que confirmi que l'aplicació funciona de debò. Si el teu projecte fa servir Wagtail, la gestió de mitja files cobra encara més importància.
La imatge Docker s'ha de poder construir de manera consistent i reproduïble. Això significa un Dockerfile entenedor on cada instrucció tingui una raó de ser, dependències del sistema clarament definides, un procés de build que no depengui de passos manuals ocults ni de configuracions locals del desenvolupador, i ordres d'arrencada ben diferenciades tant per a la part web (Gunicorn o un altre servidor WSGI) com per als workers. Sense una imatge reproduïble que puguis construir de manera idèntica en qualsevol moment i en qualsevol màquina, Kamal només aconseguiria automatitzar la fragilitat en lloc d'eliminar-la.
Les variables d'entorn i secrets han d'estar definides abans del primer desplegament. La SECRET_KEY, les credencials de la base de dades i les claus de serveis externs no han d'anar dins de la imatge ni quedar exposades al repositori. A Kamal, és habitual gestionar-los a través de .kamal/secrets o integracions amb gestors externs, i carregar aquests valors en el desplegament o en temps d'execució. Tot i així, segueix sent responsabilitat de l'equip decidir qui hi accedeix, com es roten i què passa quan canvien.
Abans d'escriure la configuració de Kamal cal tancar algunes decisions clau. On viuran PostgreSQL i Redis, com resoldre la persistència de fitxers, com s'executaran les migracions i si web i workers compartiran la mateixa imatge. Són decisions fàcils de posposar perquè no impedeixen que el primer desplegament arrenqui, però acaben apareixent com a problemes en producció.
Les dependències externes també han d'estar a punt. Un registre de contenidors accessible on publicar les imatges (Docker Hub, GitHub Container Registry o un registre privat com AWS ECR), accés SSH al servidor de destinació amb credencials correctament configurades, certificats TLS i domini resolts i apuntant al lloc correcte, i connectivitat validada entre el servidor i tots els serveis auxiliars que l'aplicació necessita. Si l'aplicació depèn de proveïdors externs per a l'enviament de correu, l'emmagatzematge de fitxers, APIs de tercers o sistemes de cues externes, la configuració i l'accessibilitat també condicionen que el desplegament realment funcioni.
El que sol oblidar-se en aquesta fase és separar bé static files i mitja files, donar a workers i tasques programades la seva pròpia configuració i revisar permisos, timeouts i el cicle de vida dels contenidors. Sense una preparació completa Kamal només automatitza un sistema fràgil, per la qual cosa cal concentrar-se a disposar de tot allò necessari abans d'iniciar la configuració de Kamal.
Traduir l'arquitectura Django a la configuració de Kamal
Quan les peces del sistema estan clares i les decisions prèvies estan preses, el següent pas consisteix a modelar aquesta arquitectura en la configuració de Kamal, i aquesta traducció resulta ser un dels exercicis més reveladors de tot el procés perquè t'obliga a fer explícit el que en altres enfocaments de desplegament sol quedar implícit, dispers entre scripts o simplement.
Rols i servidors. A Kamal el més habitual és separar almenys un rol web i un rol worker. El rol web executa Django amb Gunicorn o un altre servidor WSGI per respondre a peticions HTTP. El rol worker executa Celery, Django-RQ o la cua que utilitzeu el projecte per a tasques asíncrones. Una sola imatge de contenidor pot servir per a tots dos rols canviant únicament l'ordre d'arrencada, cosa que simplifica les versions perquè només hi ha una imatge a construir i distribuir, però exigeix que aquestes ordres estiguin ben definides, documentades i provades de forma independent.
Quan tot hi cap en un host i quan deixa de ser raonable. Per a un primer desplegament, o per a una aplicació Django amb trànsit moderat, pot ser raonable començar amb web i workers en un sol servidor. Quan el trànsit creix o Celery comença a competir amb Gunicorn per CPU i memòria, separar rols en diferents hosts deixa de ser una millora opcional i passa a ser una necessitat. El moment de pensar en aquesta separació és ara —durant la configuració inicial— encara que la implementis més endavant, perquè tenir els rols ben definits des del principi fa que la migració posterior sigui un canvi de configuració en comptes d'una reestructuració del desplegament sencer.
Imatge i build. La imatge ha de contenir tot allò necessari per executar l'aplicació de manera reproduïble: el codi, les dependències (Python i de sistema) i ordres d'arrencada ben definides. També és important que ni els secrets ni la configuració sensible quedin incrustats a la imatge, sinó que s'injectin en temps d'execució de forma independent.
Variables, secrets i configuració. A Kamal, la configuració normal i els secrets es gestionen per separat. Les variables d'entorn no sensibles es poden declarar directament a la configuració del desplegament, mentre que els secrets es guarden xifrats i Kamal els injecta als contenidors en temps d'execució. Això permet definir clarament quins valors necessita l'aplicació Django per arrencar, què comparteixen la part web i els workers, i quines dades sensibles s'han de mantenir fora de la imatge. A la pràctica, Kamal actua com a punt d'unió entre la configuració del desplegament i les credencials que necessita l'aplicació en producció.
Proxy, domini i TLS. Kamal gestiona l'entrada pública del trànsit amb kamal-proxy , que s'encarrega de publicar l'aplicació i encaminar les peticions cap al contenidor correcte. Tot i així, perquè funcioni bé necessites tenir preparat el domini, el DNS i la xarxa del servidor. Si utilitzeu HTTPS automàtic, Kamal pot obtenir certificats amb Let's Encrypt quan desplegues sobre un sol servidor i el domini apunta correctament a aquesta màquina. També convé revisar opcions com ara app_port, host, ssl, forward_headers i el healthcheck, perquè formen part de com Kamal exposa i valida l'aplicació en producció.
Volums i persistència. Si la vostra aplicació Django desa mitja files, uploads o altres dades persistents, no poden viure dins del contenidor, perquè es reemplaça a cada desplegament. Kamal permet declarar-los a la configuració mitjançant volums, muntant rutes del host dins del contenidor perquè sobrevisquin entre releases. L'alternativa és resoldre'l amb emmagatzematge extern. En tots dos casos, la idea és la mateixa: treure les dades persistents del cicle de vida efímer de la imatge.
Servicis auxiliars. No totes les peces del sistema han de viure dins del mateix desplegament de Kamal. Decidir què queda a dins i què queda a fora és una part important del disseny operatiu. PostgreSQL i Redis poden gestionar-se com a accessoris de Kamal o mantenir-se fora, però convé prendre aquesta decisió de manera explícita. En molts projectes, una opció raonable és deixar PostgreSQL com a servei extern —perquè té el seu propi cicle de vida, backups i manteniment— i fer servir Redis com a accessori lligat al desplegament de l'aplicació, ja que el seu cicle sol estar més a prop del codi i dels workers.
Particularitats de Django dins del model de desplegament
Django no és només un contenidor web que arrenca i respon peticions. Per desplegar Django amb Kamal de manera fiable cal tenir en compte algunes peces que formen part del propi cicle de release.
collectstatic ha de formar part del desplegament. Django necessita recopilar els static files abans de servir laplicació, així que collectstatic ha de tenir un lloc clar en la seqüència de release, normalment com hook. A més, convé decidir per endavant com se serviran aquests assets, ja sigui amb WhiteNoise, un proxy dedicat o un CDN, perquè aquesta decisió afecta el Dockerfile, el proxy i la validació posterior. Si collectstatic falla, l'aplicació pot arrencar i així i tot renderitzar de manera incorrecta.
Les migracions necessiten una estratègia concreta. Les migracions simples solen encaixar bé dins del flux normal de desplegament. El problema apareix amb canvis grans o destructius: taules amb molt de volum, columnes que desapareixen o canvis incompatibles amb el codi anterior. En aquests casos convé desplegar per fases i mantenir compatibilitat temporal entre codi i esquema, perquè fer rollback del codi no desfà automàticament la migració de la base de dades. Si la migració ja es va aplicar i necessites tornar a la versió anterior perquè alguna cosa ha fallat, la base de dades no retrocedeix automàticament a l'estat previ, i forçar una migració inversa en calent és una operació arriscada que pot provocar pèrdua de dades.
Web i workers comparteixen codi, però no el mateix context. En projectes amb Celery o Django-RQ, els workers poden seguir processant tasques afegides a la cua per una versió anterior del codi mentre la part web ja corre un nou release. Si canvieu una tasca o el format de les dades que espereu, es pot trencar el processament asíncron sense tocar la part web. Per això convé tractar la compatibilitat de tasques amb la mateixa cura que les migracions.
Tasques programades. Si la vostra aplicació executa tasques a intervals regulars —com enviament de correus electrònics programats, neteja de dades temporals, generació d'informes o sincronització amb serveis externs—, cal decidir on i com s'executen dins del model de desplegament. Poden viure en un procés dedicat gestionat per Kamal, delegar-se a una eina externa com un cron del sistema operatiu del host, o executar-se dins dels workers existents mitjançant un planificador com Celery Beat. Cada opció té les seves implicacions quant a fiabilitat, visibilitat i facilitat de depuració, i el més important és que la decisió sigui conscient en comptes de deixar-la a l'atzar o al costum heretat de la fase de desenvolupament.
Tot plegat, collectstatic, les migracions, els workers i les tasques programades no són detalls secundaris. Formen part del desplegament real de Django i convé tractar-los com a tal des del principi, perquè quan el projecte creixi aquesta separació conceptual serà la base sobre la qual es recolzi qualsevol evolució de l'arquitectura.
Preparar els servidors i l'entorn base
Abans del primer desplegament, el servidor ha d'estar llest per executar l'aplicació de manera estable i segura. Això inclou accés SSH amb claus, un usuari de desplegament amb permisos mínims, Docker funcionant correctament i recursos suficients per a la part web, els workers i els serveis auxiliars.
També convé verificar la connectivitat amb el registre d'imatges i amb les dependències externes de l'aplicació, com ara PostgreSQL, Redis o APIs de tercers. Si aquesta connectivitat falla, el problema no és a Kamal, sinó a l'entorn.
La xarxa ha de ser definida amb intenció. Només caldria exposar els ports necessaris, normalment 80 i 443, i la resta hauria de quedar bloquejada per tallafocs o per regles de xarxa del proveïdor. En un VPS això es pot resoldre amb ufw o iptables; a AWS, amb security groups. És una preparació bàsica, però marca la diferència entre un entorn llest per a producció i un que només sembla estar-ho.
El primer desplegament i el que sol descobrir
El primer desplegament és el moment en què tota la configuració deixa de ser teòrica i s'enfronta a la realitat del servidor, la xarxa i les dependències. Tot i que tot sembli llest, és normal que aquí apareguin suposats falsos que en local no es veien.
La seqüència amb Kamal és senzilla i predictible. Es construeix la imatge des del Dockerfile, es publica al registre, Kamal connecta per SSH, descarrega la imatge, arrenca els contenidors segons els rols definits i executa els hooks de release, com collectstatic o les migracions. Aquesta repetibilitat és precisament un dels seus avantatges: el desplegament deixa de dependre de passos manuals o de la memòria duna sola persona.
El que més sol fallar la primera vegada són variables d'entorn que falten, errors de connectivitat amb PostgreSQL o Redis, dependències del sistema que no estaven realment a la imatge, permisos incorrectes en mitja files o logs, i problemes amb static files que només apareixen en accedir pel domini real. No són errors estranys: són una part normal de validar l'entorn.
Cap d'aquests problemes no és greu si ho esperes i ho diagnostiques amb calma. La primera execució no és realment un llançament a producció sinó un exercici de validació que permet confirmar que totes les peces encaixen correctament, i tractar-la com a tal redueix la frustració i permet resoldre els problemes de forma ordenada. L'objectiu no és que tot funcioni a la primera sinó que quan alguna cosa falli sàpigues exactament on mirar per resoldre'l.
Desplegaments successius, migracions i tornada enrere
El valor real de Kamal apareix a partir del segon desplegament. Cada nou release segueix el mateix flux: construir la imatge, publicar-la, desplegar-la i executar els hooks definits. Aquesta repetibilitat permet desplegar amb més freqüència i menys incertesa, perquè el procés deixa de dependre de passos manuals. Els desplegaments freqüents amb canvis incrementals redueixen de manera significativa la taxa de fallades en producció perquè cada versió individual és més fàcil d'entendre, de verificar i de revertir si alguna cosa no funciona com s'esperava.
Les migracions continuen sent la part més sensible. Les migracions simples solen encaixar bé al flux normal de release. En canvi, els canvis destructius o que afecten molt de volum de dades convé tractar-los a part i per fases, mantenint compatibilitat temporal entre el codi i l'esquema de la base de dades. El motiu és simple: un rollback de l'aplicació no reverteix automàticament la migració. Requereix més feina de planificació, però evita l'escenari en què un desplegament fallit deixa la base de dades en un estat inconsistent.
El rollback és útil però no màgic. Kamal permet tornar ràpid a un release anterior del codi, però això no desfà canvis en dades, tasques ja processades o migracions aplicades. Per això cal pensar l'estratègia de rollback abans del problema, no durant l'incident. Un desplegament sense temps d'inactivitat ben dissenyat inclou la capacitat de retrocedir com a part del pla normal, no com un recurs d'emergència que s'improvisa quan tota la resta ha fallat.
Validacions després de desplegar
Hi ha una diferència important entre "la release ha arrencat" i "l'aplicació està realment desplegada i funcionant correctament", i donar per bo un desplegament només perquè els contenidors estan aixecats és un error que sol pagar-se amb incidents detectats pels usuaris en lloc de l'equip. Verificar que tot funciona com s'espera després de cada desplegament és tan important com el desplegament en si, i convé que aquestes verificacions estiguin definides per endavant per no dependre de la improvisació ni del record individual.
El mínim que convé validar després de cada desplegament és que l'aplicació respon des del domini correcte, que PostgreSQL i Redis estan accessibles, que els static files i mitja files segueixen servint-se bé, que almenys un flux funcional bàsic —com el login— funciona sense errors i que els workers processen tasques si hi ha processos asíncrons. També val la pena revisar els logs d'arrencada per detectar errors repetitius o errors silenciosos.
Si el vostre equip ja té monitorització en producció configurada, aquestes validacions s'integren naturalment amb les alertes existents i poden automatitzar-se en gran mesura. Si encara no la tens, aquest és un bon moment per plantejar-te-la, perquè cada desplegament és un punt de risc que la monitorització converteix en un punt de control observable i mesurable.
El desplegament com a conseqüència, no com a objectiu
Kamal encaixa molt bé per desplegar Django de forma estandarditzada en servidors propis, i resulta especialment útil per a equips petits i mitjans que necessiten un procés de desplegament repetible, predictible i documentat sense assumir la complexitat de Kubernetes o d'una plataforma d'orquestració més gran. El seu valor no és resoldre la producció sencera sinó simplificar una part concreta i crítica —l'acte de desplegar— i fer-la prou fiable perquè deixi de ser una font d'estrès.
Perquè això funcioni, l'aplicació també ha d'estar ben plantejada: arquitectura clara, secrets ben gestionats, persistència resolta, migracions compatibles i validacions després de cada versió. Si aquestes peces falten, Kamal no corregeix el problema, només accelera un procés que continua sent fràgil.
Per això el seu millor encaix sol estar en aquest punt intermedi on els scripts manuals ja no són suficients, però una orquestració complexa encara no compensa el cost d'adoptar-la i mantenir-la. En moltes aplicacions Django, aquest moment arriba abans del que sembla. Reconèixer-ho a temps és el que separa els equips que despleguen amb confiança dels que segueixen creuant els dits després de cada push.