[{"data":1,"prerenderedAt":3801},["ShallowReactive",2],{"featured-posts":3,"recent-posts":653},[4,431],{"id":5,"title":6,"body":7,"categories":413,"coverImage":417,"date":418,"description":419,"extension":420,"meta":421,"navigation":295,"path":422,"seo":423,"stem":424,"sticky":295,"tags":425,"__hash__":430},"articles/generare-sdk-javascript-waterline-con-aquasdk.md","AquaSDK: Genera SDK JavaScript in stile Waterline da specifiche OpenAPI",{"type":8,"value":9,"toc":403},"minimark",[10,23,28,56,60,65,132,184,188,226,230,318,322,329,340,344,363,366,371,391,399],[11,12,13,14,18,19,22],"p",{},"Nel mondo dello sviluppo moderno, la capacità di ",[15,16,17],"strong",{},"integrare rapidamente API"," è tanto cruciale quanto frustrante. Quante ore abbiamo perso a scrivere manualmente client SDK pieni di boilerplate? È per risolvere questo problema che ho creato ",[15,20,21],{},"AquaSDK",", uno strumento open-source che genera automaticamente SDK JavaScript con sintassi fluida e intuitiva partendo da qualsiasi specifica OpenAPI.",[24,25,27],"h2",{"id":26},"perché-automatizzare-la-generazione-di-sdk","Perché automatizzare la generazione di SDK?",[29,30,31,38,44,50],"ul",{},[32,33,34,37],"li",{},[15,35,36],{},"⏱️ Riduzione del 70% del tempo di sviluppo"," per integrazioni API",[32,39,40,43],{},[15,41,42],{},"🔒 Consistenza automatica"," tra documentazione OpenAPI e implementazione",[32,45,46,49],{},[15,47,48],{},"🚀 Esperienza developer-friendly"," con sintassi simile a Waterline ORM",[32,51,52,55],{},[15,53,54],{},"💡 Supporto nativo a Promise/async"," per codice asincrono pulito",[24,57,59],{"id":58},"funzionalità-avanzate-per-sviluppatori","Funzionalità avanzate per sviluppatori",[61,62,64],"h3",{"id":63},"per-gli-integratori-api","Per gli Integratori API",[29,66,67,118,126],{},[32,68,69,72,75,76],{},[15,70,71],{},"Sintassi a catena fluida",[73,74],"br",{},"\nInteragisci con le API come se utilizzassi un ORM:",[77,78,83],"pre",{"className":79,"code":80,"language":81,"meta":82,"style":82},"language-javascript shiki shiki-themes github-light github-dark","await api.utenti\n  .find({ ruolo: 'admin', iscrizione: { '>': '2024-01-01' } })\n  .limit(10)\n  .populate('ordini')\n  .execute();\n","javascript","",[84,85,86,94,100,106,112],"code",{"__ignoreMap":82},[87,88,91],"span",{"class":89,"line":90},"line",1,[87,92,93],{},"await api.utenti\n",[87,95,97],{"class":89,"line":96},2,[87,98,99],{},"  .find({ ruolo: 'admin', iscrizione: { '>': '2024-01-01' } })\n",[87,101,103],{"class":89,"line":102},3,[87,104,105],{},"  .limit(10)\n",[87,107,109],{"class":89,"line":108},4,[87,110,111],{},"  .populate('ordini')\n",[87,113,115],{"class":89,"line":114},5,[87,116,117],{},"  .execute();\n",[32,119,120,123,125],{},[15,121,122],{},"Validazione automatica",[73,124],{},"\nControllo degli input basato sugli schemi OpenAPI prima delle chiamate API",[32,127,128,131],{},[15,129,130],{},"Generazione completa dell'SDK","*\nAquaSDK non si limita a produrre semplici wrapper API. Ogni SDK generato include:",[77,133,137],{"className":134,"code":135,"language":136,"meta":82,"style":82},"language-bash shiki shiki-themes github-light github-dark","├── README.md # Documentazione automatica con esempi d'uso\n├── models/   # Modelli dati validati basati sugli schemi OpenAPI\n├── resources/ # Controller pronti per ogni endpoint API\n└── utils/     # Helper per query complesse\n","bash",[84,138,139,153,163,173],{"__ignoreMap":82},[87,140,141,145,149],{"class":89,"line":90},[87,142,144],{"class":143},"sScJk","├──",[87,146,148],{"class":147},"sZZnC"," README.md",[87,150,152],{"class":151},"sJ8bj"," # Documentazione automatica con esempi d'uso\n",[87,154,155,157,160],{"class":89,"line":96},[87,156,144],{"class":143},[87,158,159],{"class":147}," models/",[87,161,162],{"class":151},"   # Modelli dati validati basati sugli schemi OpenAPI\n",[87,164,165,167,170],{"class":89,"line":102},[87,166,144],{"class":143},[87,168,169],{"class":147}," resources/",[87,171,172],{"class":151}," # Controller pronti per ogni endpoint API\n",[87,174,175,178,181],{"class":89,"line":108},[87,176,177],{"class":143},"└──",[87,179,180],{"class":147}," utils/",[87,182,183],{"class":151},"     # Helper per query complesse\n",[61,185,187],{"id":186},"per-i-maintainer","Per i Maintainer",[29,189,190,218],{},[32,191,192,195],{},[15,193,194],{},"Configurazione plug-and-play",[77,196,198],{"className":134,"code":197,"language":136,"meta":82,"style":82},"generate-sdk ./swagger.json ./sdk 1.0.0 --verbose\n",[84,199,200],{"__ignoreMap":82},[87,201,202,205,208,211,215],{"class":89,"line":90},[87,203,204],{"class":143},"generate-sdk",[87,206,207],{"class":147}," ./swagger.json",[87,209,210],{"class":147}," ./sdk",[87,212,214],{"class":213},"sj4cs"," 1.0.0",[87,216,217],{"class":213}," --verbose\n",[32,219,220,223,225],{},[15,221,222],{},"Integrazione CI/CD",[73,224],{},"\nRigenera automaticamente l'SDK ad ogni aggiornamento dell'API",[24,227,229],{"id":228},"come-iniziare-in-3-passi","Come iniziare in 3 passi",[231,232,233,255,278],"ol",{},[32,234,235,236],{},"Installa il pacchetto globale:",[77,237,239],{"className":134,"code":238,"language":136,"meta":82,"style":82},"npm install -g aquasdk\n",[84,240,241],{"__ignoreMap":82},[87,242,243,246,249,252],{"class":89,"line":90},[87,244,245],{"class":143},"npm",[87,247,248],{"class":147}," install",[87,250,251],{"class":213}," -g",[87,253,254],{"class":147}," aquasdk\n",[32,256,257,258],{},"Genera il tuo SDK:",[77,259,261],{"className":134,"code":260,"language":136,"meta":82,"style":82},"generate-sdk ./api-spec.yaml ./sdk --version 1.0.0\n",[84,262,263],{"__ignoreMap":82},[87,264,265,267,270,272,275],{"class":89,"line":90},[87,266,204],{"class":143},[87,268,269],{"class":147}," ./api-spec.yaml",[87,271,210],{"class":147},[87,273,274],{"class":213}," --version",[87,276,277],{"class":213}," 1.0.0\n",[32,279,280,281],{},"Integra nel tuo progetto:",[77,282,284],{"className":79,"code":283,"language":81,"meta":82,"style":82},"import API from './sdk';\n\nconst api = new API({\n  baseUrl: 'https://api.azienda.com',\n  auth: { token: process.env.API_KEY }\n});\n",[84,285,286,291,297,302,307,312],{"__ignoreMap":82},[87,287,288],{"class":89,"line":90},[87,289,290],{},"import API from './sdk';\n",[87,292,293],{"class":89,"line":96},[87,294,296],{"emptyLinePlaceholder":295},true,"\n",[87,298,299],{"class":89,"line":102},[87,300,301],{},"const api = new API({\n",[87,303,304],{"class":89,"line":108},[87,305,306],{},"  baseUrl: 'https://api.azienda.com',\n",[87,308,309],{"class":89,"line":114},[87,310,311],{},"  auth: { token: process.env.API_KEY }\n",[87,313,315],{"class":89,"line":314},6,[87,316,317],{},"});\n",[24,319,321],{"id":320},"perché-open-source","Perché open-source?",[11,323,324,325,328],{},"AquaSDK è rilasciato sotto licenza ",[15,326,327],{},"GPL-3.0"," perché credo che:",[29,330,331,334,337],{},[32,332,333],{},"Gli strumenti fondamentali per lo sviluppo debbano essere accessibili a tutti",[32,335,336],{},"La collaborazione comunitaria produce soluzioni migliori",[32,338,339],{},"La trasparenza genera fiducia",[24,341,343],{"id":342},"prossimi-sviluppi","Prossimi sviluppi",[29,345,348,357],{"className":346},[347],"contains-task-list",[32,349,352,356],{"className":350},[351],"task-list-item",[353,354],"input",{"disabled":295,"type":355},"checkbox"," Generazione automatica di documentazione SDK",[32,358,360,362],{"className":359},[351],[353,361],{"disabled":295,"type":355}," Supporto Typescript",[364,365],"hr",{},[11,367,368],{},[15,369,370],{},"Vuoi provare AquaSDK o contribuire al progetto?",[29,372,373,383],{},[32,374,375,376],{},"🐙 GitHub: ",[377,378,382],"a",{"href":379,"rel":380},"https://github.com/enricodeleo/aquasdk",[381],"nofollow","github.com/enricodeleo/aquasdk",[32,384,385,386],{},"📦 npm: ",[377,387,390],{"href":388,"rel":389},"https://www.npmjs.com/package/aquasdk",[381],"npmjs.com/package/aquasdk",[11,392,393,394,398],{},"Per integrazioni enterprise o supporto personalizzato, ",[377,395,397],{"href":396},"mailto:hello@enricodeleo.com","contattami direttamente",".",[400,401,402],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":82,"searchDepth":96,"depth":96,"links":404},[405,406,410,411,412],{"id":26,"depth":96,"text":27},{"id":58,"depth":96,"text":59,"children":407},[408,409],{"id":63,"depth":102,"text":64},{"id":186,"depth":102,"text":187},{"id":228,"depth":96,"text":229},{"id":320,"depth":96,"text":321},{"id":342,"depth":96,"text":343},[414,415,416],"dev","tools","api","https://i2.wp.com/enricodeleo.s3.eu-south-1.amazonaws.com/images/aquasdk-cover.jpg","2025-03-11T17:00:00.000Z","Come trasformare qualsiasi specifica OpenAPI in un SDK JavaScript intuitivo con sintassi simile a Waterline ORM: la soluzione per integrazioni API veloci e senza boilerplate","md",{},"/generare-sdk-javascript-waterline-con-aquasdk",{"title":6,"description":419},"generare-sdk-javascript-waterline-con-aquasdk",[81,426,427,428,429],"openapi","sdk","rest","developer-tools","77iS9QYVT1OJ4NuE9EjRe48k0fsby1X1WLULVndW9Zg",{"id":432,"title":433,"body":434,"categories":637,"coverImage":638,"date":639,"description":640,"extension":420,"meta":641,"navigation":295,"path":642,"seo":643,"stem":644,"sticky":295,"tags":645,"__hash__":652},"articles/otto-anni-dopo-dallarchitettura-wordpress-al-boom-dei-siti-headless.md","Otto anni dopo: dall’architettura WordPress al boom dei siti headless",{"type":8,"value":435,"toc":629},[436,447,458,462,479,483,503,506,510,515,535,538,542,545,598,602,609,620],[11,437,438,439,446],{},"Nel 2016, al Meetup WordPress di Roma, parlavo di ",[377,440,443],{"href":441,"rel":442},"https://blog.enricodeleo.com/modern-gentlemens-wordpress-un-nuovo-approccio-al-web",[381],[15,444,445],{},"“Modern Gentlemen’s WordPress”",", un approccio metodico e strutturato per creare applicazioni WordPress mantenibili e performanti. Guardando indietro, quel talk fu una riflessione sullo stato dell’arte e una guida per affrontare il caos di plugin, temi pesanti e customizzazione spesso inefficiente.",[11,448,449,450,453,454,457],{},"Oggi, a distanza di otto anni, il panorama dello sviluppo web è radicalmente cambiato. Le parole chiave del 2024 sono ",[15,451,452],{},"headless CMS"," e ",[15,455,456],{},"frontend moderni",", con framework come Nuxt3 che dominano la scena. In questa retrospettiva, voglio analizzare cosa è cambiato e come WordPress continui a essere rilevante, ma in modi completamente nuovi.",[24,459,461],{"id":460},"il-passaggio-allheadless-cms","Il passaggio all'headless CMS",[11,463,464,465,467,468,471,472,475,476,398],{},"Se nel 2016 WordPress era prevalentemente utilizzato come piattaforma monolitica, oggi si sta affermando sempre più come ",[15,466,452],{},". Questo approccio separa completamente il backend dal frontend: WordPress si occupa di gestire contenuti e API, mentre il frontend viene sviluppato con tecnologie come ",[15,469,470],{},"Nuxt3",", ",[15,473,474],{},"React",", o ",[15,477,478],{},"Next.js",[61,480,482],{"id":481},"perché-scegliere-unarchitettura-headless","Perché scegliere un'architettura headless?",[29,484,485,491,497],{},[32,486,487,490],{},[15,488,489],{},"Performance superiore",": Caricamenti più rapidi grazie a frontend ottimizzati per il rendering statico o server-side.",[32,492,493,496],{},[15,494,495],{},"Flessibilità",": Il backend WordPress può alimentare diverse piattaforme (sito web, app mobile, chatbot).",[32,498,499,502],{},[15,500,501],{},"Esperienza utente avanzata",": Un frontend moderno permette di implementare interfacce altamente interattive e dinamiche.",[11,504,505],{},"WordPress, con la sua API REST nativa e GraphQL tramite plugin come WPGraphQL, si adatta perfettamente a questo paradigma. Il tuo contenuto rimane centralizzato, ma puoi costruire esperienze utente al passo con le aspettative del 2024.",[24,507,509],{"id":508},"perché-nuxt3-è-il-frontend-ideale","Perché Nuxt3 è il frontend ideale",[11,511,512,514],{},[15,513,470],{},", basato su Vue 3, si è affermato come una delle soluzioni più robuste per lo sviluppo di frontend headless. Rispetto al Nuxt2 del 2016, questa nuova versione offre:",[29,516,517,523,529],{},[32,518,519,522],{},[15,520,521],{},"Prestazioni migliorate",", grazie a Vue 3 e Vite per il bundling.",[32,524,525,528],{},[15,526,527],{},"Supporto nativo per il rendering universale",", fondamentale per SEO e performance.",[32,530,531,534],{},[15,532,533],{},"Modularità e scalabilità",", con un ecosistema che facilita l’integrazione con CMS, autenticazione e servizi cloud.",[11,536,537],{},"Con Nuxt3, puoi costruire siti che combinano il meglio del rendering statico (SSG) e server-side (SSR). Questo lo rende perfetto per e-commerce, blog e applicazioni web avanzate.",[24,539,541],{"id":540},"come-coniugare-wordpress-e-nuxt3","Come coniugare WordPress e Nuxt3",[11,543,544],{},"Ecco una roadmap per implementare un sito headless con WordPress e Nuxt3:",[231,546,547,565,581],{},[32,548,549,552,553],{},[15,550,551],{},"Preparare WordPress come CMS headless",":",[29,554,555,562],{},[32,556,557,558,561],{},"Utilizza ",[15,559,560],{},"WPGraphQL"," o la REST API per esporre i dati.",[32,563,564],{},"Ottimizza WordPress per funzionare come API server (disabilita temi e plugin non necessari).",[32,566,567,552,570],{},[15,568,569],{},"Costruire il frontend con Nuxt3",[29,571,572,575,578],{},[32,573,574],{},"Configura un’app Nuxt3 per consumare l’API di WordPress.",[32,576,577],{},"Implementa il rendering universale per ottenere un’ottima indicizzazione e prestazioni.",[32,579,580],{},"Integra strumenti moderni per immagini (Nuxt Image) e analytics.",[32,582,583,552,586],{},[15,584,585],{},"Deployment",[29,587,588],{},[32,589,590,591,471,594,597],{},"Sfrutta piattaforme moderne come ",[15,592,593],{},"Vercel",[15,595,596],{},"Netlify",", o container su cloud per una distribuzione rapida.",[24,599,601],{"id":600},"conclusioni","Conclusioni",[11,603,604,605,608],{},"Dal 2016 a oggi, la filosofia “Modern Gentlemen” ha trovato una sua naturale evoluzione. Oggi non si tratta solo di costruire applicazioni ben strutturate, ma di ",[15,606,607],{},"connettere i migliori strumenti disponibili"," per offrire esperienze utente eccezionali. Nuxt3 e l’approccio headless sono un esempio lampante di come possiamo adattarci a un web sempre più dinamico.",[11,610,611,612,619],{},"Se vuoi approfondire questo approccio, ti invito a esplorare il mio boilerplate open source ",[15,613,614],{},[377,615,618],{"href":616,"rel":617},"https://github.com/enricodeleo/wpacked",[381],"wpacked",", che rimane una solida base per chi vuole iniziare a lavorare con WordPress in maniera moderna.",[11,621,622,623,628],{},"Hai provato a creare un sito headless con WordPress e Nuxt3? Parliamone nei commenti o scrivimi ",[377,624,627],{"href":625,"rel":626},"https://www.linkedin.com/in/enricodeleo",[381],"su LinkedIn",". Sarebbe interessante confrontarci sulle sfide e sulle opportunità che questa architettura porta nel 2024.",{"title":82,"searchDepth":96,"depth":96,"links":630},[631,634,635,636],{"id":460,"depth":96,"text":461,"children":632},[633],{"id":481,"depth":102,"text":482},{"id":508,"depth":96,"text":509},{"id":540,"depth":96,"text":541},{"id":600,"depth":96,"text":601},[414],"https://i2.wp.com/enricodeleo.s3.eu-south-1.amazonaws.com/images/otto-anni-dopo-dallarchitettura-wordpress-al-boom-dei-siti-headles.jpg","2024-12-11T12:00:00.000Z","Una retrospettiva sull'evoluzione delle applicazioni WordPress dal 2016 al 2024 e la rivoluzione dei siti headless con Nuxt3.",{},"/otto-anni-dopo-dallarchitettura-wordpress-al-boom-dei-siti-headless",{"title":433,"description":640},"otto-anni-dopo-dallarchitettura-wordpress-al-boom-dei-siti-headless",[646,647,648,649,650,651],"wordpress","nuxt3","headless","vue3","frontend","cms","tzHRnbi4BAHubpIahh1b0Mmoc57Fdi72dWvb8ayO_fo",[654,1012,1217,1386,1903,3637],{"id":655,"title":656,"body":657,"categories":995,"coverImage":998,"date":999,"description":1000,"extension":420,"meta":1001,"navigation":295,"path":1002,"seo":1003,"stem":1004,"sticky":1005,"tags":1006,"__hash__":1011},"articles/velocita-senza-giudizio.md","Velocità senza giudizio",{"type":8,"value":658,"toc":986},[659,665,668,675,678,681,687,694,698,701,708,722,729,735,738,742,748,755,758,769,772,779,787,790,794,797,804,815,818,825,830,833,836,843,847,850,853,856,859,865,868,873,876,880,886,889,896,899,910,914,920,923,934,939,942,945,950,954,957,964,967,978,981],[11,660,661],{},[662,663,664],"em",{},"Il vibe coding non ha inventato il codice scritto male. Ha solo tolto l'attrito.",[11,666,667],{},"Ho visto un backend con l'autenticazione hardcodata nel frontend. Password admin in chiaro, visibile a chiunque aprisse DevTools. Non era vibe coding — era 2018, dev umani, trovati su Upwork.",[11,669,670,671,674],{},"Ve lo dico perché quello che sta succedendo adesso ",[15,672,673],{},"non è una novità",". È la stessa roba, più veloce.",[11,676,677],{},"Ho visto Google Sheets usato come database. Collassava a quattro utenti. I fondatori si sono sorpresi.",[11,679,680],{},"Ho visto funzionalità dichiarate implementate che erano solo API vuote senza niente dietro. L'ho visto fare a dev umani. L'ho visto fare a Claude Opus 4.6, che in questo momento è il modello più capace di Anthropic. Ho visto test scritti per passare, non per verificare.",[682,683,684],"blockquote",{},[11,685,686],{},"Un sistema che si auto-certifica è più pericoloso di uno che fallisce apertamente.",[11,688,689,690,693],{},"Il problema non è l'AI. È che la velocità che offre può farti dimenticare che costruire software è ",[15,691,692],{},"fondamentalmente un atto cognitivo"," — non di scrittura.",[24,695,697],{"id":696},"il-software-non-è-testo","Il software non è testo",[11,699,700],{},"Questa è la cosa che l'entusiasmo attorno al vibe coding dimentica sistematicamente.",[11,702,703,704,707],{},"Il software non è testo. È un ",[15,705,706],{},"modello formale della realtà"," — un sistema di regole che descrive come un dominio si comporta, come gli stati cambiano, come le eccezioni vengono gestite, come il tempo e la concorrenza e il fallimento vengono trattati.",[11,709,710,711,714,715,718,719,398],{},"Scrivere codice non è mai stato il problema difficile. Il problema difficile è capire ",[662,712,713],{},"cosa"," scrivere — e ",[662,716,717],{},"perché",". È identificare i confini del dominio, le invarianti che devono reggere, i casi limite che il business non ti ha detto perché non sapeva di doverlo fare, le implicazioni che una scelta architetturale avrà tra sei mesi quando i requisiti cambieranno — ",[15,720,721],{},"perché cambiano sempre",[11,723,724,725,728],{},"Questa comprensione non si ottiene velocemente. Si ottiene attraverso iterazioni, conversazioni, errori, correzioni, notti a chiedersi perché quella cosa non funziona come dovrebbe. È quella che Michael Polanyi chiamava ",[662,726,727],{},"conoscenza tacita"," — sapere che non si riesce a trasferire completamente in parole, che risiede nell'esperienza accumulata, nei pattern riconosciuti, nelle intuizioni costruite su decine di progetti.",[11,730,731,734],{},[15,732,733],{},"L'AI non ha questa conoscenza."," Ha la media statistica di quello che è stato scritto su internet riguardo a problemi simili al tuo.",[11,736,737],{},"Che non è la stessa cosa.",[24,739,741],{"id":740},"la-trappola-della-perfezione-apparente","La trappola della perfezione apparente",[11,743,744,745,398],{},"C'è qualcosa di specifico nell'AI che aggrava tutto questo: ",[15,746,747],{},"il codice che produce sembra sempre scritto bene",[11,749,750,751,754],{},"È ben nominato, ha i commenti nei posti giusti, segue le convenzioni, usa i pattern corretti. Non sembra il codice di qualcuno che non sa quello che fa — sembra il codice di qualcuno che sa ",[662,752,753],{},"esattamente"," quello che fa.",[11,756,757],{},"Questo è il problema.",[11,759,760,761,764,765,768],{},"Il codice sbagliato scritto male ti ferma. Lo vedi, lo senti, ti insospettisce. Attiva il tuo senso critico prima ancora che tu abbia capito cosa fa. Il ",[15,762,763],{},"codice sbagliato scritto bene"," attraversa la code review senza attivare nessun campanello d'allarme, supera i test, va in produzione. E quando si rompe — ",[662,766,767],{},"perché si rompe"," — la forma corretta del codice rende ancora più difficile localizzare il problema concettuale che ci sta sotto.",[11,770,771],{},"Stai cercando un bug in codice che non sembra buggy. Stai cercando un'assunzione sbagliata in codice che sembra ragionevole.",[11,773,774,775,778],{},"Nel 1986 Fred Brooks scriveva che la difficoltà essenziale del software non è accidentale — non riguarda la sintassi, i compilatori, la velocità di scrittura. Riguarda la ",[15,776,777],{},"complessità concettuale intrinseca"," dei sistemi che costruiamo. Quarant'anni dopo, l'AI ha eliminato quasi completamente la difficoltà accidentale. Quella essenziale è rimasta intatta.",[682,780,781],{},[11,782,783,786],{},[662,784,785],{},"\"No silver bullet.\"","\n— Fred Brooks, 1986",[11,788,789],{},"E ora che la difficoltà accidentale è sparita, la difficoltà essenziale è più esposta che mai. Ma è anche più facile da non vedere, perché l'output che la nasconde sembra così convincente.",[24,791,793],{"id":792},"il-modello-della-realtà","Il modello della realtà",[11,795,796],{},"Quando chiedi all'AI di costruire qualcosa, quello che ricevi non è una soluzione.",[11,798,799,800,803],{},"È una ",[15,801,802],{},"interpretazione"," del problema che hai descritto.",[11,805,806,807,810,811,814],{},"L'AI costruisce un modello della realtà basato su quello che gli hai detto — e quello che gli hai detto è inevitabilmente incompleto, perché la conoscenza del dominio che hai in testa non si trasferisce per intero in un prompt. Il gap tra il problema che hai ",[662,808,809],{},"in testa"," e il problema che l'AI ha ",[662,812,813],{},"capito"," è sempre presente. A volte è trascurabile. A volte è la differenza tra un sistema che regge e uno che collassa al primo caso limite reale.",[11,816,817],{},"La velocità non ti dà il tempo di misurare quel gap. Peggio: la velocità e la perfezione apparente dell'output creano attivamente l'illusione che il gap non esista.",[11,819,820,821,824],{},"Questo è il motivo per cui ",[15,822,823],{},"\"funziona\" non è mai abbastanza"," come criterio di accettazione.",[11,826,827],{},[662,828,829],{},"Funziona rispetto a cosa?",[11,831,832],{},"Rispetto ai test che l'AI ha scritto per passare — costruiti attorno agli stessi casi che aveva in testa quando ha scritto il codice, in un loop chiuso che non include nessuna realtà esterna? Rispetto alla demo con dati puliti e percorsi felici? O rispetto alla logica reale del dominio, con tutti i casi limite che solo tu conosci perché ci hai lavorato dentro?",[11,834,835],{},"Salvatore Sanfilippo ha sollevato un problema analogo sulla code review: lo stato mentale di chi scrive non è trasferibile al reviewer. Il reviewer vede il testo, non il ragionamento che ha prodotto quel testo. O puntualizza cose superficiali, oppure non comprende abbastanza da vedere il problema vero.",[11,837,838,839,842],{},"Con l'AI il problema si radicalizza: ",[15,840,841],{},"l'AI non ha stato mentale da trasferire",". Ha prodotto output ottimizzando per la coerenza interna del testo, non per la corrispondenza con la tua realtà. Il reviewer — che sei tu — deve colmare quel gap da solo. Se non ti fermi a farlo, nessuno lo farà.",[24,844,846],{"id":845},"let-it-sink","Let it sink",[11,848,849],{},"C'è una pratica che ogni ingegnere con abbastanza cicatrici ha interiorizzato: dormirci sopra.",[11,851,852],{},"Non per pigrizia. Per necessità cognitiva.",[11,854,855],{},"Il cervello umano non elabora i problemi complessi in modo lineare e sequenziale. Elabora in parallelo, spesso al di sotto della soglia della coscienza. È per questo che le soluzioni migliori arrivano sotto la doccia, in macchina, la mattina appena svegli — non davanti allo schermo quando stai cercando attivamente la risposta. I problemi che non vedi nel momento emergono dopo, quando torni con occhi freschi e il cervello ha avuto il tempo di connettere pattern che la concentrazione attiva non riesce a vedere.",[11,857,858],{},"Non è misticismo. È neuroscienze. La modalità diffusa del cervello è essenziale per l'insight, per la comprensione profonda, per accorgersi delle incongruenze che la modalità focalizzata salta perché è troppo dentro il problema.",[11,860,861,862],{},"Con l'AI quella pratica diventa ancora più importante, e ancora più facile da saltare. Perché in pochi minuti hai davanti qualcosa che sembra completo. L'effort che hai speso è minimo, quindi la sensazione di investimento è bassa, quindi la soglia per dichiararlo fatto si abbassa. ",[15,863,864],{},"Non hai faticato per arrivare lì, quindi non senti il bisogno di proteggerti dall'errore di aver faticato invano.",[11,866,867],{},"Ma \"sembra completo\" e \"è corretto\" sono due cose diverse — e la velocità di produzione dell'AI ha reso quella distinzione più sottile che mai.",[682,869,870],{},[11,871,872],{},"Fermarsi non è perdere il vantaggio della velocità. È il momento in cui verifichi che quella velocità ti abbia portato nella direzione giusta.",[11,874,875],{},"Senza quel momento, stai solo andando veloce verso il posto sbagliato — e ci arrivi prima.",[24,877,879],{"id":878},"la-code-review-non-basta","La code review non basta",[11,881,882,883,398],{},"La risposta istintiva a tutto questo è: ",[662,884,885],{},"\"per questo c'è la code review\"",[11,887,888],{},"Ma la code review, così come è praticata nella maggior parte dei team, non risolve il problema che stiamo descrivendo.",[11,890,891,892,895],{},"La code review tradizionale è ottima per trovare bug sintattici, violazioni di convenzioni, problemi di sicurezza ovvi. È molto meno efficace per valutare se le ",[15,893,894],{},"decisioni architetturali sono corrette",", se il modello del dominio rispecchia la realtà, se le assunzioni implicite nel codice sono valide.",[11,897,898],{},"Con l'AI il problema si amplifica: il codice generato è sintatticamente inattaccabile. Il reviewer scorre, non trova niente che attivi i campanelli d'allarme standard, approva. Il problema concettuale che stava sotto passa indisturbato.",[11,900,901,902,905,906,909],{},"La code review utile in questo contesto non è ",[662,903,904],{},"\"questo codice è scritto bene?\""," — quella risposta è quasi sempre sì. È ",[662,907,908],{},"\"questo codice fa quello che dovrebbe fare nel contesto del dominio reale?\""," — e per rispondere devi avere la conoscenza del dominio che l'AI non ha, devi aver capito i requisiti abbastanza da sapere cosa verificare, devi aver lasciato che la soluzione sedimentasse abbastanza da poterla vedere con distacco critico.",[24,911,913],{"id":912},"il-debito-che-non-vedi","Il debito che non vedi",[11,915,916,917,398],{},"Il debito tecnico generato senza giudizio ha una caratteristica precisa: ",[15,918,919],{},"è silenzioso",[11,921,922],{},"Non si manifesta subito. Si accumula in decisioni prese per default dall'AI che non erano le tue decisioni — ma ora sono nel codice, e il codice è in produzione. In architetture che reggono il caso d'uso che hai descritto ma non quello successivo. In assunzioni implicite che l'AI ha fatto riempiendo i gap del tuo prompt con la media di quello che ha visto in training.",[11,924,925,926,929,930,933],{},"Ward Cunningham, che il termine \"debito tecnico\" lo ha inventato, intendeva qualcosa di specifico: il debito ",[662,927,928],{},"deliberato",", contratto consapevolmente per andare più veloci ora con l'intenzione di ripagarlo dopo. Non il debito ",[662,931,932],{},"accidentale",", quello che accumuli senza saperlo perché non hai capito abbastanza bene il problema.",[11,935,936],{},[15,937,938],{},"Il debito deliberato è uno strumento legittimo. Il debito accidentale è ignoranza capitalizzata.",[11,940,941],{},"Il vibe coding senza giudizio produce quasi esclusivamente debito accidentale. Perché la velocità impedisce la comprensione, e senza comprensione non puoi nemmeno scegliere consapevolmente di indebitarti — ti indebiti e basta, senza saperlo, senza poterlo quantificare, senza un piano per ripagarlo.",[11,943,944],{},"E quando emerge, emerge nel momento peggiore. Quando c'è trazione. Quando ci sono utenti reali. Quando il costo di sistemare è un ordine di grandezza superiore a quello che sarebbe stato all'inizio.",[682,946,947],{},[11,948,949],{},"Il conto arriva sempre. La velocità determina solo quanto in fretta lo accumuli.",[24,951,953],{"id":952},"la-velocità-è-un-mezzo","La velocità è un mezzo",[11,955,956],{},"L'AI nello sviluppo è straordinaria. La uso ogni giorno.",[11,958,959,960,963],{},"Ma la velocità non è il fine — è un mezzo. Il fine è costruire qualcosa che ",[15,961,962],{},"rispecchi la logica che avevi in testa",", che regga i casi limite del dominio reale, che qualcuno possa capire e modificare tra un anno senza maledire chi lo ha scritto.",[11,965,966],{},"Se la velocità ti impedisce di verificare che questo sia vero, non stai andando più veloce. Stai solo sbagliando più in fretta. Con più righe di codice. Con più fiducia. Con meno possibilità di accorgertene prima che diventi costoso.",[11,968,969,970,973,974,977],{},"La differenza tra un ingegnere che usa l'AI bene e uno che la usa male non è tecnica. ",[15,971,972],{},"È cognitiva."," È la capacità di fermarsi, lasciare che le cose sedimentino, tornare con distacco critico e chiedersi: questo rispecchia davvero quello che volevo? O sto guardando qualcosa che ",[662,975,976],{},"sembra"," quello che volevo?",[11,979,980],{},"Sono domande scomode da fare quando hai appena passato un pomeriggio produttivo e lo schermo è pieno di codice nuovo e i test passano.",[11,982,983],{},[662,984,985],{},"Falle lo stesso.",{"title":82,"searchDepth":96,"depth":96,"links":987},[988,989,990,991,992,993,994],{"id":696,"depth":96,"text":697},{"id":740,"depth":96,"text":741},{"id":792,"depth":96,"text":793},{"id":845,"depth":96,"text":846},{"id":878,"depth":96,"text":879},{"id":912,"depth":96,"text":913},{"id":952,"depth":96,"text":953},[996,997],"Dev","AI","https://i2.wp.com/enricodeleo.s3.eu-south-1.amazonaws.com/images/velocita-senza-giudizio.png","2026-04-03T10:00:00.000Z","Il vibe coding non ha inventato il codice scritto male. Ha solo tolto l'attrito. E la velocità, senza il tempo di valutare, produce solo errori più rapidi.",{},"/velocita-senza-giudizio",{"title":656,"description":1000},"velocita-senza-giudizio",false,[1007,1008,1009,1010],"ai","vibe-coding","engineering","build-in-public","U75B5WaPnYhOsgue02Cp92PwZioiIXFh6SRZMrizYok",{"id":1013,"title":1014,"body":1015,"categories":1204,"coverImage":1205,"date":1206,"description":1207,"extension":420,"meta":1208,"navigation":295,"path":1209,"seo":1210,"stem":1211,"sticky":1005,"tags":1212,"__hash__":1216},"articles/la-storia-si-ripete.md","La storia si ripete",{"type":8,"value":1016,"toc":1196},[1017,1022,1030,1034,1037,1040,1052,1058,1061,1064,1068,1074,1077,1083,1087,1090,1096,1099,1103,1123,1130,1133,1140,1150,1154,1157,1163,1166,1169,1174,1178,1183,1193],[11,1018,1019],{},[662,1020,1021],{},"Graph database, MongoDB, vector database dedicati. Il pattern è sempre lo stesso. Solo i nomi cambiano.",[11,1023,1024,1025,1029],{},"Nel ",[377,1026,1028],{"href":1027},"/il-cms-in-c-che-non-ho-mai-scritto","post precedente"," ho raccontato di come nel 2015 ho scelto \"il solito\" WordPress per creare una piattaforma usata da decine di migliaia di persone. Ma c'è un'altra storia di quegli anni che vale la pena raccontare.",[24,1031,1033],{"id":1032},"_2015-i-graph-database-erano-il-futuro-nosql-il-presente","2015: i graph database erano il futuro, noSQL il presente",[11,1035,1036],{},"Ogni conferenza, ogni blog post, ogni dev entusiasta. \"Le foreign key non scalano. I join sono roba vecchia. Il mondo è fatto di connessioni.\" Neo4j, Cypher, slide piene di nodi colorati e frecce.",[11,1038,1039],{},"Sullo stesso tono di guerra ai classici relazionali, le milioni di persone che si sono riversata su una unica combo, che quasi faceva da sinonimo a startup: nodejs + mongodb.",[11,1041,1042,1043,471,1046,471,1049,398],{},"Partecipavo spesso a demo day tecnici dove CTO di altre startup raccontavano come stavano impostando la loro tecnologia.\nRicordo ancora uno ha esordire, appunto, con il classico dell'epoca: \"useremo node in accoppiata con mongo!\".\nPoi ha iniziato a descrivere il dominio: ",[662,1044,1045],{},"\"la relazione con\"",[662,1047,1048],{},"\"la relazione di\"",[662,1050,1051],{},"\"questo è collegato a quello tramite quell'altro\"",[11,1053,1054,1055],{},"Ho detto: ",[15,1056,1057],{},"\"Che follia sarebbe stata salvare le relazioni in un db... relazionale, vero?\"",[11,1059,1060],{},"Oggi uso Postgres per quasi tutto. Quando mi serve qualcosa in più pesco a piene mani da estensioni per lo stesso : pgvector per i vettori, timescale per time series, pg_textsearch per full text con ranking.",[11,1062,1063],{},"Graph database: zero.",[24,1065,1067],{"id":1066},"cosa-è-successo","Cosa è successo",[11,1069,1070,1071],{},"Niente di drammatico. ",[15,1072,1073],{},"Postgres è andato avanti.",[11,1075,1076],{},"Recursive CTE, jsonb, estensioni per tutto. Ha cannibalizzato il 90% dei casi d'uso senza aggiungere un componente infrastrutturale in più da mantenere, sincronizzare, monitorare e pagare.\nIl costo operativo di un grafo dedicato non è banale: lo sharding è complicato, e il modello mentale è diverso da quello relazionale che la maggior parte degli sviluppatori ha già interiorizzato.",[11,1078,1079,1080,398],{},"Risultato: ottimo strumento per nicchie specifiche — fraud detection su scala enterprise, knowledge graph in grandi organizzazioni. Per il 95% dei progetti: ",[15,1081,1082],{},"overkill",[24,1084,1086],{"id":1085},"la-stessa-storia-prima","La stessa storia, prima",[11,1088,1089],{},"Prima dei graph database c'era stato MongoDB.",[11,1091,1092,1095],{},[662,1093,1094],{},"\"I join non scalano\""," — ripetuto come un mantra da chi non aveva mai avuto problemi di scala.\nDue anni dopo: array di userId dentro il documento ordine, ma alcuni stringhe, alcuni numeri altri ObjectId e manca il 3% dei riferimenti, e nessuno sa perché.",[11,1097,1098],{},"MongoDB era genuinamente utile per alcuni casi d'uso e anch'io l'ho usato tantissimo (più frequentemento a fianco anziché in sostituzione).\nIl problema era che veniva usato per tutto, perché era nuovo, perché era cool, perché usarlo sembrava una scelta moderna.",[24,1100,1102],{"id":1101},"il-pattern-è-sempre-lo-stesso","Il pattern è sempre lo stesso",[231,1104,1105,1108,1111,1114,1117,1120],{},[32,1106,1107],{},"Tecnologia nuova risolve problemi reali in casi specifici",[32,1109,1110],{},"Viene presentata con casi d'uso di aziende con scala che il 99% dei team non avrà mai",[32,1112,1113],{},"Viene adottata come soluzione generale",[32,1115,1116],{},"Chi usa la tecnologia \"noiosa\" sembra un fossile",[32,1118,1119],{},"Arriva il momento dei conti",[32,1121,1122],{},"La tecnologia noiosa è ancora lì, qualcuno propone un refactor \"per irrobustire\" (leggasi tornare a schemi e contratti solidi), che durerà un anno.",[11,1124,1125,1126,1129],{},"C'è un concetto che si chiama ",[15,1127,1128],{},"Lindy Effect",": una tecnologia che esiste da vent'anni probabilmente esisterà altri vent'anni.",[11,1131,1132],{},"Ve lo dice uno che è smanettone e enthusiast dalla nascita: conoscere tutto, sperimentare tutto, ma in produzione... Dipende.",[11,1134,1135,1136,1139],{},"Il nostro mestiere è ",[15,1137,1138],{},"identificare contesti in cui è necessario operare scelte \"a mestiere\""," anche considerando aree di rischio come il supporto sul lungo periodo,\nla reperibilità (e dunque i costi) di risorse schillate in quella tecnologia col crescere del team, trasferimento di competenze, disponibilità di estensioni/librerie già pronte e battle-tested.",[11,1141,1142,1145,1146,1149],{},[15,1143,1144],{},"E lo so che riusare qualcosa che usi da 20 anni è noioso",", ma a volte è anche il servizio più professionale che possiamo rendere. Per il brivido della novità basta un po' di pazienza e\ncertamente l'universo ci manderà il progetto in cui avrà veramente senso utilizzare la novità. Nel frattempo ci sono i vari progetti personali ",[662,1147,1148],{},"for fun"," come sfogo.",[24,1151,1153],{"id":1152},"sta-succedendo-adesso","Sta succedendo adesso",[11,1155,1156],{},"Pinecone, Weaviate, Chroma. Vector database dedicati, presentati come componente necessario di qualsiasi architettura AI.",[11,1158,1159,1160,398],{},"Anche qui: non è che siano inutili. È che nella stragrande maggioranza dei casi ",[15,1161,1162],{},"non ne hai bisogno",[11,1164,1165],{},"Una ricerca ibrida full-text con BM25 + pgvector risolve il grosso — con il vantaggio di avere tutto nello stesso database, relazioni intatte, zero sincronizzazioni, zero componenti aggiuntivi da mantenere. Fino a circa mezzo milione di record la differenza di performance rispetto a un vector database dedicato è risibile. E la maggior parte dei progetti non arriverà mai a mezzo milione di record.",[11,1167,1168],{},"Il costo dell'infrastruttura esotica lo paghi sempre dopo, mai subito. E \"dopo\" coincide quasi sempre con il momento peggiore: trazione reale, investitori che guardano, utenti che si lamentano.",[11,1170,1171],{},[15,1172,1173],{},"La storia è ciclica. Solo i nomi cambiano.",[24,1175,1177],{"id":1176},"il-mio-mantra","Il mio mantra",[682,1179,1180],{},[11,1181,1182],{},"Minimum diff, less moving parts.",[11,1184,1185,1186,1189,1190],{},"Nei progetti ho una regola che mi porto dietro da anni: ",[15,1187,1188],{},"minimum diff, less moving parts",". Ogni componente aggiuntivo è una dipendenza, una cosa che può rompersi e che ha side effects a volte impliciti. Una cosa che qualcuno\ndeve capire, mantenere, aggiornare. ",[15,1191,1192],{},"Il costo non è mai solo tecnico — è cognitivo, operativo, economico.",[11,1194,1195],{},"Scegliere la tecnologia più \"dritta\" che risolve il problema non è una scorciatoia. È il mestiere.",{"title":82,"searchDepth":96,"depth":96,"links":1197},[1198,1199,1200,1201,1202,1203],{"id":1032,"depth":96,"text":1033},{"id":1066,"depth":96,"text":1067},{"id":1085,"depth":96,"text":1086},{"id":1101,"depth":96,"text":1102},{"id":1152,"depth":96,"text":1153},{"id":1176,"depth":96,"text":1177},[996],"https://i2.wp.com/enricodeleo.s3.eu-south-1.amazonaws.com/images/la-storia-si-ripete.png","2026-03-30T10:00:00.000Z","Nel 2015 i graph database erano il futuro. Oggi uso Postgres per quasi tutto. Nel mezzo: MongoDB, ObjectId misti, e il solito conto arrivato dopo. Sta succedendo di nuovo con i vector database.",{},"/la-storia-si-ripete",{"title":1014,"description":1207},"la-storia-si-ripete",[1213,1214,1009,1215,1010],"postgres","database","tech-debt","VEFCqWkv1Yjj6bCK7VDZSq71yRGNeyfN3gYqOWZux44",{"id":1218,"title":1219,"body":1220,"categories":1374,"coverImage":1376,"date":1377,"description":1378,"extension":420,"meta":1379,"navigation":295,"path":1027,"seo":1380,"stem":1381,"sticky":1005,"tags":1382,"__hash__":1385},"articles/il-cms-in-c-che-non-ho-mai-scritto.md","Il CMS in C che non ho mai scritto",{"type":8,"value":1221,"toc":1369},[1222,1227,1231,1237,1251,1257,1260,1265,1272,1275,1279,1285,1308,1311,1318,1320,1322,1326,1336,1342,1348,1353,1358,1361,1364],[11,1223,1224],{},[662,1225,1226],{},"Nel 2015 valevi quanto il linguaggio che usavi. Questa è la storia di come ho ignorato quella regola e cosa è successo dopo.",[24,1228,1230],{"id":1229},"la-scelta","La scelta",[11,1232,1233,1234,398],{},"Nel 2015 ho passato qualche giorno a considerare seriamente di ",[15,1235,1236],{},"scrivere un CMS da zero in C",[11,1238,1239,1240,1243,1244,1247,1248,398],{},"Non era follia pura (certo, ci si avvicinava eh). Volendo, avrei avuto le competenze per farlo. Il problema era un altro: nel mondo dev di quegli anni ",[15,1241,1242],{},"valevi quanto il linguaggio che usavi",".\nNella narrativa da ",[662,1245,1246],{},"street credibility"," del tempo, più il linguaggio aveva una curva di apprendimento alto e più eri forte. C, di certo, era rispettabilità. PHP o JavaScript roba da pivelli. ",[15,1249,1250],{},"WordPress non ne parliamo proprio",[11,1252,1253,1254,398],{},"Poi ho detto: ",[662,1255,1256],{},"naaaaaaaaaaaaah",[11,1258,1259],{},"Dovevo costruire una piattaforma per la vendita di fumetti digitali. Utenti, contenuti, pagamenti, file protetti da download. Da solo, con poco budget che volevo però destinato a fornire a me e il mio socio non-tech un posto in cui dormire\ne coprire le spese necessarie a portare i primi contratti. Deadline vita o morte: 6 mesi per partecipare a un investor day presentando non solo l'app ma già dei risultati contati per numero di utenti.",[11,1261,1262],{},[15,1263,1264],{},"Ho preso WordPress e l'ho piegato a quello che mi serviva.",[11,1266,1267,1268,1271],{},"Non perché fosse la scelta più figa. Ma perché ",[15,1269,1270],{},"conoscevo quella codebase a memoria",". Sapevo come si comportava sotto carico, dove tendeva a rompersi, come estenderla. E soprattutto sapevo dove guardare quando qualcosa andava storto alle 2 di notte — cosa che succede sempre, invariabilmente, al momento peggiore.",[11,1273,1274],{},"Un CMS in C avrei ancora finito di scriverlo adesso.",[24,1276,1278],{"id":1277},"quello-che-è-uscito-fuori","Quello che è uscito fuori",[11,1280,1281,1282,552],{},"In sei mesi, team di sviluppo, UI, UX, DevOps composto da... ",[15,1283,1284],{},"soltanto me",[29,1286,1287,1290,1293,1296,1302,1305],{},[32,1288,1289],{},"Backend della piattaforma",[32,1291,1292],{},"API REST per l'app mobile",[32,1294,1295],{},"App iOS",[32,1297,1298,1299],{},"Sistema di cifratura a chiave asincrona per la protezione dei file, ",[15,1300,1301],{},"registrato SIAE",[32,1303,1304],{},"Infrastruttura su due macchine sincronizzate con load balancer, gestita con Ansible",[32,1306,1307],{},"HHVM per la compilazione jit di php, visto che certo PHP 8 non esisteva ancora",[11,1309,1310],{},"Il back office era \"gratis\", e il solito WordPress che tutti gli interni sapevano già usare. Praticamente zero onboarding: lo usava chiunque dovesse usarlo, senza aprire un ticket.",[11,1312,1313,1314,1317],{},"Prima settimana dal lancio: 9.000 signup. ",[15,1315,1316],{},"app del mese su App Store Italia",". 400k raccolti dagli investitori.",[364,1319],{},[364,1321],{},[24,1323,1325],{"id":1324},"il-punto","Il punto",[11,1327,1328,1329,453,1332,1335],{},"C'è una differenza tra ",[15,1330,1331],{},"non conoscere le alternative",[15,1333,1334],{},"conoscerle tutte e scegliere quella che funziona"," nel contesto e coi vincoli reali.",[11,1337,1338,1339,398],{},"Il rischio non è \"devo imparare la sintassi\" o \"l'eleganza della soluzione\". È che ",[15,1340,1341],{},"non conosci ancora i failure mode",[11,1343,1344,1345,398],{},"È come scegliere tra andare in gara con una 500 che guidi da 10 anni — sai che la terza gratta un po', quanti newton applicare allo sterzo, come frena sul bagnato — oppure con un veicolo di ultima generazione che si pilota usando il ",[15,1346,1347],{},"pronzione",[11,1349,1350],{},[15,1351,1352],{},"Tu dirai: ma che è il pronzione?",[11,1354,1355],{},[15,1356,1357],{},"Esatto.",[11,1359,1360],{},"Ed è proprio questo il problema. Con lo stack nuovo stai debuggando nel buio alle 2 di notte qualcosa per cui non hai ancora un nome.",[11,1362,1363],{},"Il CMS in C sarebbe stato figo da raccontare ai meetup.",[11,1365,1366],{},[15,1367,1368],{},"I 9.000 signup erano meglio.",{"title":82,"searchDepth":96,"depth":96,"links":1370},[1371,1372,1373],{"id":1229,"depth":96,"text":1230},{"id":1277,"depth":96,"text":1278},{"id":1324,"depth":96,"text":1325},[996,1375],"Startup","https://i2.wp.com/enricodeleo.s3.eu-south-1.amazonaws.com/images/la-500-che-vinceva.png","2026-03-28T10:00:00.000Z","Nel 2015 avrei potuto scrivere un CMS in C. Ho scelto WordPress. Sei mesi dopo avevo 9.000 signup, app del mese su App Store Italia e 400k raccolti dagli investitori. Team di sviluppo: io.",{},{"title":1219,"description":1378},"il-cms-in-c-che-non-ho-mai-scritto",[646,1383,1009,1384,1010],"startup","indie","Q99QWwKOb-D7xX75KyiaDlui2yrSzAfsnqC1ps5KQv0",{"id":1387,"title":1388,"body":1389,"categories":1888,"coverImage":1891,"date":1892,"description":1893,"extension":420,"meta":1894,"navigation":295,"path":1895,"seo":1896,"stem":1897,"sticky":1005,"tags":1898,"__hash__":1902},"articles/marketing-engineering-il-caos-non-scala.md","Marketing Engineering: software mindset applicato al business",{"type":8,"value":1390,"toc":1875},[1391,1396,1400,1408,1411,1424,1430,1436,1447,1456,1461,1470,1473,1477,1480,1494,1501,1507,1511,1517,1525,1528,1531,1548,1552,1558,1564,1575,1584,1588,1591,1596,1599,1613,1616,1620,1626,1629,1640,1646,1650,1653,1673,1676,1693,1703,1707,1717,1720,1731,1734,1745,1750,1754,1760,1763,1774,1777,1788,1791,1795,1807,1810,1824,1833,1837,1840,1849,1852,1869,1872],[11,1392,1393],{},[662,1394,1395],{},"Caso reale: budget limitato, geografia \"a lentiggine\" e una domanda semplice solo in apparenza. In questo post racconto come ho trasformato quel caos in un processo decisionale operativo.",[24,1397,1399],{"id":1398},"quando-il-problema-non-è-tecnico-ma-il-metodo-sì","Quando il problema non è tecnico, ma il metodo sì",[11,1401,1402,1403,1405],{},"Nel marketing complesso non basta il solo intuito.",[73,1404],{},[15,1406,1407],{},"Serve rigore operativo.",[11,1409,1410],{},"Per me significa due cose:",[29,1412,1413,1418],{},[32,1414,1415],{},[15,1416,1417],{},"non decidere a sensazione",[32,1419,1420,1423],{},[15,1421,1422],{},"non delegare ciecamente alla piattaforma",", sperando che la sua AI ottimizzi da sola",[11,1425,1426,1427],{},"La richiesta, in questo caso, era diretta: ",[15,1428,1429],{},"\"Abbiamo questa situazione, idee?\"",[11,1431,1432,1433,1435],{},"Sembra una domanda semplice.",[73,1434],{},"\nIn realtà contiene tre problemi diversi:",[29,1437,1438,1441,1444],{},[32,1439,1440],{},"un problema di business (budget limitato)",[32,1442,1443],{},"un problema operativo (territorio frammentato)",[32,1445,1446],{},"un problema decisionale (come prioritizzare in modo razionale)",[11,1448,1449,1450,1452,1453,398],{},"Quindi no: non era \"solo\" un tema di targeting.",[73,1451],{},"\nEra un tema di ",[15,1454,1455],{},"allocazione sotto vincoli",[682,1457,1458],{},[11,1459,1460],{},"In una situazione così non serve il bazooka: servono proiettili d'argento.",[11,1462,1463,1464,1466,1467,398],{},"Un chiarimento sul ruolo: non nasco come marketer operativo.",[73,1465],{},"\nVengo coinvolto quando il tema marketing smette di essere solo execution e diventa un problema di ",[15,1468,1469],{},"allocazione, dati e qualità decisionale",[11,1471,1472],{},"In questo caso ho applicato criteri, ragionamenti e strategie che uso da anni in ambito tech/software: scomporre il problema, definire vincoli espliciti, progettare un processo replicabile e misurare ogni decisione.",[24,1474,1476],{"id":1475},"_1-la-situazione-di-partenza-cosa-rendeva-il-problema-difficile","1) La situazione di partenza: cosa rendeva il problema difficile",[11,1478,1479],{},"Il contesto era questo:",[29,1481,1482,1485,1488,1491],{},[32,1483,1484],{},"copertura reale limitata a micro-zone non continue",[32,1486,1487],{},"base clienti potenziale distribuita in modo irregolare",[32,1489,1490],{},"pressione a partire in fretta",[32,1492,1493],{},"budget non sufficiente per \"testare tutto\"",[11,1495,1496,1497,1500],{},"Io questa configurazione l'ho ribattezzata ",[15,1498,1499],{},"\"geografia a lentiggine\"",": a macchia di leopardo sarebbe stato già un lusso.",[11,1502,1503,1504,1506],{},"In pratica, ogni euro aveva costo opportunità alto.",[73,1505],{},"\nSe lo mettevi nel posto sbagliato, non perdevi solo budget: perdevi tempo di apprendimento.",[24,1508,1510],{"id":1509},"_2-perché-il-solo-intuito-non-bastava","2) Perché il solo intuito non bastava",[11,1512,1513,1514,1516],{},"L'intuito è utile, soprattutto nelle prime fasi.",[73,1515],{},"\nMa qui c'erano due limiti strutturali:",[29,1518,1519,1522],{},[32,1520,1521],{},"troppa variabilità geografica per ragionare \"a colpo d'occhio\"",[32,1523,1524],{},"troppi decisori con opinioni plausibili ma non confrontabili",[11,1526,1527],{},"Quando tutti hanno una buona ipotesi, il rischio è restare paralizzati o scegliere la voce più forte, non la scelta migliore.",[11,1529,1530],{},"Serviva quindi un criterio:",[29,1532,1533,1538,1543],{},[32,1534,1535],{},[15,1536,1537],{},"replicabile",[32,1539,1540],{},[15,1541,1542],{},"spiegabile al business",[32,1544,1545],{},[15,1546,1547],{},"traducibile in execution media",[24,1549,1551],{"id":1550},"_3-perché-non-lasciare-tutto-alla-piattaforma","3) Perché non lasciare tutto alla piattaforma",[11,1553,1554,1555,1557],{},"Domanda legittima: \"non può pensarci la piattaforma con la sua AI?\"",[73,1556],{},"\nIn parte sì. Ma con un costo.",[11,1559,1560,1561,1563],{},"Le piattaforme ottimizzano dopo aver visto abbastanza distribuzione.",[73,1562],{},"\nQuella fase richiede volume, quindi budget. E nelle fasi iniziali può significare:",[29,1565,1566,1569,1572],{},[32,1567,1568],{},"dispersione",[32,1570,1571],{},"targeting troppo ampio",[32,1573,1574],{},"segnali rumorosi prima di convergere",[11,1576,1577,1578,398,1581,1583],{},"Quando il budget è stretto, ",[15,1579,1580],{},"non puoi comprare apprendimento indefinito",[73,1582],{},"\nDevi arrivare con una tesi iniziale più robusta.",[24,1585,1587],{"id":1586},"_4-la-domanda-giusta-prima-della-tecnica","4) La domanda giusta prima della tecnica",[11,1589,1590],{},"Prima di parlare di ML, ho riformulato la domanda così:",[11,1592,1593],{},[15,1594,1595],{},"Come trasformiamo una geografia complessa in una lista ordinata di priorità di investimento?",[11,1597,1598],{},"Da qui derivano i requisiti del metodo:",[29,1600,1601,1604,1607,1610],{},[32,1602,1603],{},"partire da dati realmente disponibili",[32,1605,1606],{},"gestire irregolarità e outlier",[32,1608,1609],{},"produrre output operativi, non solo analitici",[32,1611,1612],{},"mantenere la logica trasparente per il team",[11,1614,1615],{},"Solo a questo punto ha senso discutere di strumenti.",[24,1617,1619],{"id":1618},"_5-dati-minimi-utili-il-vero-punto-di-leva","5) Dati minimi utili: il vero punto di leva",[11,1621,1622,1623,398],{},"Il principio è semplice: ",[15,1624,1625],{},"dataset minimo utile prima, complessità dopo",[11,1627,1628],{},"Per questo caso bastavano:",[29,1630,1631,1634,1637],{},[32,1632,1633],{},"coordinate lat/lon dei punti servibili",[32,1635,1636],{},"eventuale peso commerciale per punto",[32,1638,1639],{},"vincoli operativi della piattaforma Ads (es. raggio minimo)",[11,1641,1642,1643,1645],{},"Non serviva un data lake.",[73,1644],{},"\nServiva una base coerente per prendere decisioni migliori delle alternative manuali.",[24,1647,1649],{"id":1648},"_6-dove-entra-ml-e-perché-qui-ha-senso","6) Dove entra ML (e perché qui ha senso)",[11,1651,1652],{},"Solo dopo il framing decisionale, ML e statistica diventano utili:",[29,1654,1655,1661,1667],{},[32,1656,1657,1660],{},[15,1658,1659],{},"la statistica"," definisce la scala reale del problema (e protegge dagli outlier)",[32,1662,1663,1666],{},[15,1664,1665],{},"il ML"," identifica pattern geografici non ovvi a vista",[32,1668,1669,1672],{},[15,1670,1671],{},"il ranking"," trasforma l'analisi in priorità",[11,1674,1675],{},"Pipeline essenziale:",[231,1677,1678,1681,1684,1687,1690],{},[32,1679,1680],{},"stima scala locale con k-NN",[32,1682,1683],{},"clustering per densità con DBSCAN",[32,1685,1686],{},"metriche cluster (numerosità, dispersione, centroide, valore)",[32,1688,1689],{},"ranking delle aree per priorità investimento",[32,1691,1692],{},"traduzione in azione Ads (centroide + raggio operativo)",[11,1694,1695,1698,1700],{},[662,1696,1697],{},"Il punto non è usare ML \"per innovare\".",[73,1699],{},[662,1701,1702],{},"Il punto è ridurre arbitrarietà nelle decisioni di budget.",[24,1704,1706],{"id":1705},"_7-loutput-che-serve-davvero-al-business","7) L'output che serve davvero al business",[11,1708,1709,1712,1714],{},[15,1710,1711],{},"L'output utile non è una mappa bella da vedere.",[73,1713],{},[15,1715,1716],{},"È una lista prioritaria argomentabile in riunione.",[11,1718,1719],{},"Per ogni area candidata:",[29,1721,1722,1725,1728],{},[32,1723,1724],{},"livello di priorità",[32,1726,1727],{},"razionale quantitativo",[32,1729,1730],{},"vincolo operativo per l'attivazione",[11,1732,1733],{},"A quel punto la discussione cambia:",[29,1735,1736,1739,1742],{},[32,1737,1738],{},"dove abbiamo maggiore densità utile?",[32,1740,1741],{},"dove il valore commerciale giustifica maggiore dispersione?",[32,1743,1744],{},"quanta quota di rumore siamo disposti ad accettare?",[11,1746,1747],{},[15,1748,1749],{},"Meno opinioni generiche, più trade-off espliciti.",[24,1751,1753],{"id":1752},"_8-cosa-cambia-nel-modo-di-lavorare","8) Cosa cambia nel modo di lavorare",[11,1755,1756,1757,1759],{},"Il cambiamento non è solo tecnico.",[73,1758],{},"\nÈ anche organizzativo.",[11,1761,1762],{},"Prima:",[29,1764,1765,1768,1771],{},[32,1766,1767],{},"ogni campagna riparte quasi da zero",[32,1769,1770],{},"criteri impliciti",[32,1772,1773],{},"forte dipendenza da esperienza individuale",[11,1775,1776],{},"Dopo:",[29,1778,1779,1782,1785],{},[32,1780,1781],{},"criterio esplicito",[32,1783,1784],{},"processo replicabile",[32,1786,1787],{},"iterazioni comparabili nel tempo",[11,1789,1790],{},"In sintesi: meno improvvisazione, più sistema.",[24,1792,1794],{"id":1793},"_9-il-passo-successivo-testare-non-raccontare","9) Il passo successivo: testare, non raccontare",[11,1796,1797,1798,398,1801,1803,1804,398],{},"Questo approccio ",[15,1799,1800],{},"non promette scorciatoie",[73,1802],{},"\nPromette una cosa più utile: ",[15,1805,1806],{},"ipotesi testabili",[11,1808,1809],{},"Prima di scalare, definisco sempre:",[29,1811,1812,1815,1818,1821],{},[32,1813,1814],{},"metrica primaria",[32,1816,1817],{},"finestra di osservazione",[32,1819,1820],{},"criterio di successo/fallimento",[32,1822,1823],{},"regole di iterazione",[11,1825,1826,1827,1829,1830,1832],{},"Se conferma, si scala.",[73,1828],{},"\nSe non conferma, si corregge.",[73,1831],{},"\nIn entrambi i casi, si apprende.",[24,1834,1836],{"id":1835},"il-mio-punto-di-vista","Il mio punto di vista",[11,1838,1839],{},"Quando un problema sembra insormontabile, spesso è solo poco strutturato.",[11,1841,1842,1843,1845,1846,1848],{},"Il caos non scala.",[73,1844],{},"\nLe opinioni non scalano.",[73,1847],{},"\nLe scorciatoie non scalano.",[11,1850,1851],{},"Scala un metodo:",[29,1853,1854,1857,1860,1863,1866],{},[32,1855,1856],{},"domanda giusta",[32,1858,1859],{},"dati minimi utili",[32,1861,1862],{},"statistica robusta",[32,1864,1865],{},"ML pragmatico",[32,1867,1868],{},"decisioni trasparenti",[11,1870,1871],{},"Per me, questo è Marketing Engineering: usare dati e metodo per prendere decisioni migliori, prima di spendere.",[11,1873,1874],{},"È per questo che mi piace il mio lavoro: prima la creatività, per esplorare davvero lo spazio del problema; poi il rigore scientifico, per trasformare intuizioni in decisioni solide e razionali.",{"title":82,"searchDepth":96,"depth":96,"links":1876},[1877,1878,1879,1880,1881,1882,1883,1884,1885,1886,1887],{"id":1398,"depth":96,"text":1399},{"id":1475,"depth":96,"text":1476},{"id":1509,"depth":96,"text":1510},{"id":1550,"depth":96,"text":1551},{"id":1586,"depth":96,"text":1587},{"id":1618,"depth":96,"text":1619},{"id":1648,"depth":96,"text":1649},{"id":1705,"depth":96,"text":1706},{"id":1752,"depth":96,"text":1753},{"id":1793,"depth":96,"text":1794},{"id":1835,"depth":96,"text":1836},[997,1889,1890],"Marketing","Data Science","https://i2.wp.com/enricodeleo.s3.eu-south-1.amazonaws.com/images/data-analaysis-ml-adv.png","2026-02-28T10:00:00.000Z","Quando il problema non è tecnico, ma il metodo sì: software mindset, dati e AI pragmatica per passare da investimenti a pioggia a scelte di marketing mirate.",{},"/marketing-engineering-il-caos-non-scala",{"title":1388,"description":1893},"marketing-engineering-il-caos-non-scala",[1899,1900,1901],"marketing","fractional-cto","growth","1oKTBeRQFlvNR0c3gFJTAgIW9uWXVJ-zAx8jKaVUKvI",{"id":1904,"title":1905,"body":1906,"categories":3619,"coverImage":3623,"date":3624,"description":3625,"extension":420,"meta":3626,"navigation":295,"path":3627,"seo":3628,"stem":3629,"sticky":1005,"tags":3630,"__hash__":3636},"articles/nanopi-r76s-router-2-5gbps-performance-speed-boost.md","Ottimizzare le prestazioni del router NanoPi R76S con OpenWrt: da 600 Mbps a oltre 2 Gbps",{"type":8,"value":1907,"toc":3599},[1908,1932,1936,1951,1962,1973,1977,1984,1989,2025,2043,2045,2049,2056,2059,2086,2090,2093,2121,2125,2152,2158,2160,2164,2175,2179,2187,2190,2206,2213,2216,2323,2325,2329,2336,2348,2650,2656,2672,2674,2678,2684,2697,3189,3193,3207,3209,3216,3223,3226,3310,3314,3328,3330,3334,3341,3344,3366,3368,3372,3383,3393,3434,3436,3440,3443,3493,3496,3504,3506,3510,3513,3566,3568,3574,3582,3596],[11,1909,1910,1911,1914,1915,1918,1919,1922,1923,398,1926,1928,1929,398],{},"Questa settimana ho sostituito il mio amatissimo ",[15,1912,1913],{},"EdgeRouter X SFP"," (un router a mio avviso ottimo per qualità/prezzo ma purtroppo limitato a 1gbps)\ncon un ",[15,1916,1917],{},"NanoPi R76S",", un piccolo router ARMv8 basato su ",[15,1920,1921],{},"Rockchip RK3576",", pubblicizzato con porte ",[15,1924,1925],{},"2.5GbE",[73,1927],{},"\nSulla carta, doveva essere perfetto ma nella pratica… ",[15,1930,1931],{},"non lo era affatto",[24,1933,1935],{"id":1934},"perché-ho-scelto-il-friendlyelec-nanopi-r76s","Perché ho scelto il FriendlyELEC NanoPi R76S",[11,1937,1938,1939,1942,1943,1946,1947,1950],{},"Quando ho deciso di sostituire il mio vecchio EdgeRouter X SFP, cercavo qualcosa di compatto, silenzioso e moderno, ma soprattutto ",[15,1940,1941],{},"abbastanza potente da gestire la mia nuova connessione 2.5gbps FTTH"," senza sudare troppo.\nDopo un po’ di ricerche mi sono imbattuto nel ",[15,1944,1945],{},"FriendlyELEC NanoPi R76S"," — un piccolo router con un look quasi da mini NUC, ma costruito attorno a un ",[15,1948,1949],{},"SoC Rockchip RK3576"," con ben otto core ARM (quattro Cortex-A76 e quattro Cortex-A55) e due porte Ethernet 2.5 GbE basate su chip Realtek RTL8125B.",[11,1952,1953,1954,1957,1958,1961],{},"Oltre alla potenza, mi ha convinto anche la forma fisica: ",[15,1955,1956],{},"il case in alluminio anodizzato nero",", le ",[15,1959,1960],{},"dimensioni davvero ridotte"," e il fatto che si alimenti tramite USB-C.\nNel mio piccolo armadietto server domestico — dove ogni centimetro e ogni alimentatore contano — questo dettaglio ha fatto la differenza.\nFinalmente niente più brick da 12 V con spinotto, ma un semplice cavo USB-C come quello di uno smartphone.",[11,1963,1964,1965,1968,1969,1972],{},"A bordo c’è ",[15,1966,1967],{},"FriendlyWrt",", la versione personalizzata di ",[15,1970,1971],{},"OpenWrt"," mantenuta da FriendlyELEC, che di base è già un ottimo punto di partenza.",[24,1974,1976],{"id":1975},"la-delusione","La delusione",[11,1978,1979,1980,1983],{},"Dopo l’installazione pulita di ",[15,1981,1982],{},"FriendlyWrt 24.10 (OpenWrt 24.10)",", entusiasta di poter finalemnte testare la nuova conenssione multi-gigabit\nho eseguito i primi test con la CLI di Ookla (speedtest) pregustando già la soddisfazione di vedere schizzare la banda.",[11,1985,1986],{},[15,1987,1988],{},"I risultati sono stati deludenti:",[1990,1991,1992,2008],"table",{},[1993,1994,1995],"thead",{},[1996,1997,1998,2002,2005],"tr",{},[1999,2000,2001],"th",{},"Test",[1999,2003,2004],{},"Download",[1999,2006,2007],{},"Upload",[2009,2010,2011],"tbody",{},[1996,2012,2013,2019,2022],{},[2014,2015,2016],"td",{},[15,2017,2018],{},"Before tuning",[2014,2020,2021],{},"606 Mbps",[2014,2023,2024],{},"771 Mbps",[11,2026,2027,2028,2031,2032,2034,2035,2038,2039,2042],{},"Ho iniziato a fare dei test più approfonditi, ",[84,2029,2030],{},"htop"," alla mano, e il collo di bottiglia era evidente: la CPU si saturava su un solo core durante i test, mentre gli altri restavano praticamente inattivi.",[73,2033],{},"\nNonostante il ",[84,2036,2037],{},"flow_offloading"," fosse attivo nel firewall, ",[15,2040,2041],{},"il kernel non stava distribuendo correttamente gli interrupt (IRQ)"," delle interfacce di rete sui vari core.",[364,2044],{},[24,2046,2048],{"id":2047},"diagnosi-irq-rps-xps-e-cpu-governor","Diagnosi: IRQ, RPS, XPS e CPU governor",[11,2050,2051,2052,2055],{},"Il SoC ",[15,2053,2054],{},"RK3576"," supporta 8 core, ma senza una corretta gestione delle code e delle interrupt mask, OpenWrt tende ad assegnare tutto a un singolo core (con esattezza lo 0).",[11,2057,2058],{},"Ho quindi individuato tre aree di intervento:",[231,2060,2061,2074,2080],{},[32,2062,2063,2066,2067,471,2070,2073],{},[15,2064,2065],{},"Distribuire gli IRQ"," delle interfacce di rete (",[84,2068,2069],{},"eth0",[84,2071,2072],{},"eth1",") su più core CPU",[32,2075,2076,2079],{},[15,2077,2078],{},"Abilitare e ottimizzare RPS/XPS"," (Receive/Transmit Packet Steering)",[32,2081,2082,2085],{},[15,2083,2084],{},"Forzare la CPU in modalità “performance”"," per evitare scaling aggressivo della frequenza",[24,2087,2089],{"id":2088},"️-tuning-v1-rpsxps-e-sysctl-base","⚙️ Tuning v1 — RPS/XPS e Sysctl base",[11,2091,2092],{},"La prima iterazione ha incluso:",[29,2094,2095,2101,2108,2114],{},[32,2096,2097,2098],{},"Abilitazione di ",[84,2099,2100],{},"net.core.rps_sock_flow_entries=65536",[32,2102,2103,2104,2107],{},"Configurazione di RPS e XPS su tutti i core (",[84,2105,2106],{},"0xff",")",[32,2109,2110,2111],{},"Applicazione permanente via ",[84,2112,2113],{},"/etc/hotplug.d/net/99-optimize-network",[32,2115,2116,2117,2120],{},"Disattivazione di ",[84,2118,2119],{},"irqbalance"," per gestire manualmente le CPU affinity",[61,2122,2124],{"id":2123},"risultato","Risultato",[1990,2126,2127,2137],{},[1993,2128,2129],{},[1996,2130,2131,2133,2135],{},[1999,2132,2001],{},[1999,2134,2004],{},[1999,2136,2007],{},[2009,2138,2139],{},[1996,2140,2141,2146,2149],{},[2014,2142,2143],{},[15,2144,2145],{},"Tuning v1",[2014,2147,2148],{},"706 Mbps",[2014,2150,2151],{},"928 Mbps",[11,2153,2154,2155,2157],{},"Il miglioramento è stato tangibile (almeno lato upload), ma non risolutivo.",[73,2156],{},"\nLa saturazione CPU era distribuita meglio, ma ancora incompleta: i pacchetti non sfruttavano tutti i core disponibili.",[364,2159],{},[24,2161,2163],{"id":2162},"tuning-finale-irq-affinity-cpu-performance-mode","🔥 Tuning finale — IRQ affinity + CPU performance mode",[11,2165,2166,2167,2170,2171,2174],{},"Il tuning finale che porta ai ~2 Gbps stabili il ",[15,2168,2169],{},"NanoPi R76S (RK3576)"," con ",[15,2172,2173],{},"FriendlyWrt/OpenWrt 24.10"," richiede l'introduzione di diversi parametri finalizzati prevalentemente a distribuire il carico sui (tanti) core disponibili e distribuire i flussi di rete coerentemente.",[61,2176,2178],{"id":2177},"_1️⃣-sysctl-tuning-del-network-stack","🧩 1️⃣  Sysctl – Tuning del network stack",[11,2180,2181,2182],{},"📄 ",[15,2183,2184],{},[84,2185,2186],{},"/etc/sysctl.d/60-rps.conf",[11,2188,2189],{},"→ imposta le entry per i flussi RPS (Receive Packet Steering)",[77,2191,2193],{"className":134,"code":2192,"language":136,"meta":82,"style":82},"net.core.rps_sock_flow_entries = 65536\n",[84,2194,2195],{"__ignoreMap":82},[87,2196,2197,2200,2203],{"class":89,"line":90},[87,2198,2199],{"class":143},"net.core.rps_sock_flow_entries",[87,2201,2202],{"class":147}," =",[87,2204,2205],{"class":213}," 65536\n",[11,2207,2181,2208],{},[15,2209,2210],{},[84,2211,2212],{},"/etc/sysctl.d/99-network-tune.conf",[11,2214,2215],{},"→ parametri generali di rete + TCP tuning (coerenti con BBR)",[77,2217,2219],{"className":134,"code":2218,"language":136,"meta":82,"style":82},"# Fair Queueing + congestion control\nnet.core.default_qdisc = fq\nnet.ipv4.tcp_congestion_control = bbr\n\n# TCP tuning generali\nnet.ipv4.tcp_fastopen = 3\nnet.ipv4.tcp_tw_reuse = 2\nnet.ipv4.ip_local_port_range = 10000 65535\nnet.ipv4.tcp_fin_timeout = 30\n\n# Gestione traffico burst\nnet.core.netdev_max_backlog = 250000\n",[84,2220,2221,2226,2236,2246,2250,2255,2265,2276,2290,2301,2306,2312],{"__ignoreMap":82},[87,2222,2223],{"class":89,"line":90},[87,2224,2225],{"class":151},"# Fair Queueing + congestion control\n",[87,2227,2228,2231,2233],{"class":89,"line":96},[87,2229,2230],{"class":143},"net.core.default_qdisc",[87,2232,2202],{"class":147},[87,2234,2235],{"class":147}," fq\n",[87,2237,2238,2241,2243],{"class":89,"line":102},[87,2239,2240],{"class":143},"net.ipv4.tcp_congestion_control",[87,2242,2202],{"class":147},[87,2244,2245],{"class":147}," bbr\n",[87,2247,2248],{"class":89,"line":108},[87,2249,296],{"emptyLinePlaceholder":295},[87,2251,2252],{"class":89,"line":114},[87,2253,2254],{"class":151},"# TCP tuning generali\n",[87,2256,2257,2260,2262],{"class":89,"line":314},[87,2258,2259],{"class":143},"net.ipv4.tcp_fastopen",[87,2261,2202],{"class":147},[87,2263,2264],{"class":213}," 3\n",[87,2266,2268,2271,2273],{"class":89,"line":2267},7,[87,2269,2270],{"class":143},"net.ipv4.tcp_tw_reuse",[87,2272,2202],{"class":147},[87,2274,2275],{"class":213}," 2\n",[87,2277,2279,2282,2284,2287],{"class":89,"line":2278},8,[87,2280,2281],{"class":143},"net.ipv4.ip_local_port_range",[87,2283,2202],{"class":147},[87,2285,2286],{"class":213}," 10000",[87,2288,2289],{"class":213}," 65535\n",[87,2291,2293,2296,2298],{"class":89,"line":2292},9,[87,2294,2295],{"class":143},"net.ipv4.tcp_fin_timeout",[87,2297,2202],{"class":147},[87,2299,2300],{"class":213}," 30\n",[87,2302,2304],{"class":89,"line":2303},10,[87,2305,296],{"emptyLinePlaceholder":295},[87,2307,2309],{"class":89,"line":2308},11,[87,2310,2311],{"class":151},"# Gestione traffico burst\n",[87,2313,2315,2318,2320],{"class":89,"line":2314},12,[87,2316,2317],{"class":143},"net.core.netdev_max_backlog",[87,2319,2202],{"class":147},[87,2321,2322],{"class":213}," 250000\n",[364,2324],{},[61,2326,2328],{"id":2327},"️-2️⃣-script-principale-applica-rpsxps-manualmente","⚙️ 2️⃣  Script principale – Applica RPS/XPS manualmente",[11,2330,2181,2331],{},[15,2332,2333],{},[84,2334,2335],{},"/usr/local/sbin/apply-rpsxps.sh",[11,2337,2338,2339,2342,2343,453,2345,2347],{},"→ comando indipendente che puoi eseguire a mano o al boot\n(applica ",[84,2340,2341],{},"MASK=ff"," su ",[84,2344,2069],{},[84,2346,2072],{},", e imposta i flussi globali)",[77,2349,2351],{"className":134,"code":2350,"language":136,"meta":82,"style":82},"#!/bin/sh\nMASK_HEX=ff\nFLOW_ENTRIES=65536\nDEVS=\"eth0 eth1\"\nlogger -t rpsxps \"start apply (devs: $DEVS)\"\n\nsysctl -q -w net.core.rps_sock_flow_entries=\"$FLOW_ENTRIES\"\n\nfor IF in $DEVS; do\n  for RX in /sys/class/net/$IF/queues/rx-*; do\n    [ -d \"$RX\" ] || continue\n    echo \"$MASK_HEX\" > \"$RX/rps_cpus\"\n    echo 32768 > \"$RX/rps_flow_cnt\" 2>/dev/null\n  done\n  for TX in /sys/class/net/$IF/queues/tx-*; do\n    [ -d \"$TX\" ] || continue\n    echo \"$MASK_HEX\" > \"$TX/xps_cpus\"\n  done\ndone\nlogger -t rpsxps \"done apply (mask=$MASK_HEX, flows=$FLOW_ENTRIES)\"\n",[84,2352,2353,2358,2371,2381,2391,2411,2415,2435,2439,2456,2480,2506,2528,2551,2557,2578,2598,2618,2623,2629],{"__ignoreMap":82},[87,2354,2355],{"class":89,"line":90},[87,2356,2357],{"class":151},"#!/bin/sh\n",[87,2359,2360,2364,2368],{"class":89,"line":96},[87,2361,2363],{"class":2362},"sVt8B","MASK_HEX",[87,2365,2367],{"class":2366},"szBVR","=",[87,2369,2370],{"class":147},"ff\n",[87,2372,2373,2376,2378],{"class":89,"line":102},[87,2374,2375],{"class":2362},"FLOW_ENTRIES",[87,2377,2367],{"class":2366},[87,2379,2380],{"class":147},"65536\n",[87,2382,2383,2386,2388],{"class":89,"line":108},[87,2384,2385],{"class":2362},"DEVS",[87,2387,2367],{"class":2366},[87,2389,2390],{"class":147},"\"eth0 eth1\"\n",[87,2392,2393,2396,2399,2402,2405,2408],{"class":89,"line":114},[87,2394,2395],{"class":143},"logger",[87,2397,2398],{"class":213}," -t",[87,2400,2401],{"class":147}," rpsxps",[87,2403,2404],{"class":147}," \"start apply (devs: ",[87,2406,2407],{"class":2362},"$DEVS",[87,2409,2410],{"class":147},")\"\n",[87,2412,2413],{"class":89,"line":314},[87,2414,296],{"emptyLinePlaceholder":295},[87,2416,2417,2420,2423,2426,2429,2432],{"class":89,"line":2267},[87,2418,2419],{"class":143},"sysctl",[87,2421,2422],{"class":213}," -q",[87,2424,2425],{"class":213}," -w",[87,2427,2428],{"class":147}," net.core.rps_sock_flow_entries=\"",[87,2430,2431],{"class":2362},"$FLOW_ENTRIES",[87,2433,2434],{"class":147},"\"\n",[87,2436,2437],{"class":89,"line":2278},[87,2438,296],{"emptyLinePlaceholder":295},[87,2440,2441,2444,2447,2450,2453],{"class":89,"line":2292},[87,2442,2443],{"class":2366},"for",[87,2445,2446],{"class":2362}," IF ",[87,2448,2449],{"class":2366},"in",[87,2451,2452],{"class":2362}," $DEVS; ",[87,2454,2455],{"class":2366},"do\n",[87,2457,2458,2461,2464,2466,2469,2472,2475,2478],{"class":89,"line":2303},[87,2459,2460],{"class":2366},"  for",[87,2462,2463],{"class":2362}," RX ",[87,2465,2449],{"class":2366},[87,2467,2468],{"class":147}," /sys/class/net/",[87,2470,2471],{"class":2362},"$IF",[87,2473,2474],{"class":147},"/queues/rx-*",[87,2476,2477],{"class":2362},"; ",[87,2479,2455],{"class":2366},[87,2481,2482,2485,2488,2491,2494,2497,2500,2503],{"class":89,"line":2308},[87,2483,2484],{"class":2362},"    [ ",[87,2486,2487],{"class":2366},"-d",[87,2489,2490],{"class":147}," \"",[87,2492,2493],{"class":2362},"$RX",[87,2495,2496],{"class":147},"\"",[87,2498,2499],{"class":2362}," ] ",[87,2501,2502],{"class":2366},"||",[87,2504,2505],{"class":2366}," continue\n",[87,2507,2508,2511,2513,2516,2518,2521,2523,2525],{"class":89,"line":2314},[87,2509,2510],{"class":213},"    echo",[87,2512,2490],{"class":147},[87,2514,2515],{"class":2362},"$MASK_HEX",[87,2517,2496],{"class":147},[87,2519,2520],{"class":2366}," >",[87,2522,2490],{"class":147},[87,2524,2493],{"class":2362},[87,2526,2527],{"class":147},"/rps_cpus\"\n",[87,2529,2531,2533,2536,2538,2540,2542,2545,2548],{"class":89,"line":2530},13,[87,2532,2510],{"class":213},[87,2534,2535],{"class":213}," 32768",[87,2537,2520],{"class":2366},[87,2539,2490],{"class":147},[87,2541,2493],{"class":2362},[87,2543,2544],{"class":147},"/rps_flow_cnt\"",[87,2546,2547],{"class":2366}," 2>",[87,2549,2550],{"class":147},"/dev/null\n",[87,2552,2554],{"class":89,"line":2553},14,[87,2555,2556],{"class":2366},"  done\n",[87,2558,2560,2562,2565,2567,2569,2571,2574,2576],{"class":89,"line":2559},15,[87,2561,2460],{"class":2366},[87,2563,2564],{"class":2362}," TX ",[87,2566,2449],{"class":2366},[87,2568,2468],{"class":147},[87,2570,2471],{"class":2362},[87,2572,2573],{"class":147},"/queues/tx-*",[87,2575,2477],{"class":2362},[87,2577,2455],{"class":2366},[87,2579,2581,2583,2585,2587,2590,2592,2594,2596],{"class":89,"line":2580},16,[87,2582,2484],{"class":2362},[87,2584,2487],{"class":2366},[87,2586,2490],{"class":147},[87,2588,2589],{"class":2362},"$TX",[87,2591,2496],{"class":147},[87,2593,2499],{"class":2362},[87,2595,2502],{"class":2366},[87,2597,2505],{"class":2366},[87,2599,2601,2603,2605,2607,2609,2611,2613,2615],{"class":89,"line":2600},17,[87,2602,2510],{"class":213},[87,2604,2490],{"class":147},[87,2606,2515],{"class":2362},[87,2608,2496],{"class":147},[87,2610,2520],{"class":2366},[87,2612,2490],{"class":147},[87,2614,2589],{"class":2362},[87,2616,2617],{"class":147},"/xps_cpus\"\n",[87,2619,2621],{"class":89,"line":2620},18,[87,2622,2556],{"class":2366},[87,2624,2626],{"class":89,"line":2625},19,[87,2627,2628],{"class":2366},"done\n",[87,2630,2632,2634,2636,2638,2641,2643,2646,2648],{"class":89,"line":2631},20,[87,2633,2395],{"class":143},[87,2635,2398],{"class":213},[87,2637,2401],{"class":147},[87,2639,2640],{"class":147}," \"done apply (mask=",[87,2642,2515],{"class":2362},[87,2644,2645],{"class":147},", flows=",[87,2647,2431],{"class":2362},[87,2649,2410],{"class":147},[11,2651,2652,2653],{},"📌  ",[15,2654,2655],{},"Permessi:",[77,2657,2659],{"className":134,"code":2658,"language":136,"meta":82,"style":82},"chmod +x /usr/local/sbin/apply-rpsxps.sh\n",[84,2660,2661],{"__ignoreMap":82},[87,2662,2663,2666,2669],{"class":89,"line":90},[87,2664,2665],{"class":143},"chmod",[87,2667,2668],{"class":147}," +x",[87,2670,2671],{"class":147}," /usr/local/sbin/apply-rpsxps.sh\n",[364,2673],{},[61,2675,2677],{"id":2676},"_3️⃣-hook-net-rpsxps-automatico-su-ogni-interfaccia","🔁 3️⃣  Hook NET – RPS/XPS automatico su ogni interfaccia",[11,2679,2181,2680],{},[15,2681,2682],{},[84,2683,2113],{},[11,2685,2686,2687,453,2690,2693,2694,398],{},"Si attiva ogni volta che nasce una nuova interfaccia (eth*, VLAN, PPPoE).\nGarantisce che anche ",[84,2688,2689],{},"eth0.835",[84,2691,2692],{},"pppoe-wan"," ricevano ",[84,2695,2696],{},"rps_cpus=ff",[77,2698,2700],{"className":134,"code":2699,"language":136,"meta":82,"style":82},"#!/bin/sh\n[ \"$ACTION\" = \"add\" ] || exit 0\ncase \"$DEVICENAME\" in eth*|pppoe-*) : ;; *) exit 0 ;; esac\n\nMASK_HEX=ff\nFLOW_ENTRIES=65536\nlogger -t rpsxps \"net hook: $DEVICENAME ACTION=$ACTION (mask=$MASK_HEX flows=$FLOW_ENTRIES)\"\nsysctl -q -w net.core.rps_sock_flow_entries=\"$FLOW_ENTRIES\"\n\nPARENT=\"$(basename \"$(readlink -f /sys/class/net/$DEVICENAME/lower_* 2>/dev/null || true)\")\"\n[ -n \"$PARENT\" ] || PARENT=\"$DEVICENAME\"\n\napply_one() {\n  IF=\"$1\"\n  for i in 1 2 3 4 5; do\n    [ -e \"/sys/class/net/$IF/queues/rx-0/rps_cpus\" ] && break\n    sleep 1\n  done\n  for RX in /sys/class/net/\"$IF\"/queues/rx-*; do\n    [ -e \"$RX/rps_cpus\" ] || continue\n    echo \"$MASK_HEX\" > \"$RX/rps_cpus\"\n    echo 32768 > \"$RX/rps_flow_cnt\" 2>/dev/null\n  done\n  for TX in /sys/class/net/\"$IF\"/queues/tx-*; do\n    [ -e \"$TX/xps_cpus\" ] || continue\n    echo \"$MASK_HEX\" > \"$TX/xps_cpus\"\n  done\n}\n\napply_one \"$PARENT\"\napply_one \"$DEVICENAME\"\n",[84,2701,2702,2706,2733,2782,2786,2794,2802,2832,2846,2850,2894,2923,2927,2935,2949,2977,2998,3006,3010,3030,3049,3068,3087,3092,3112,3132,3151,3156,3162,3167,3178],{"__ignoreMap":82},[87,2703,2704],{"class":89,"line":90},[87,2705,2357],{"class":151},[87,2707,2708,2711,2713,2716,2718,2720,2723,2725,2727,2730],{"class":89,"line":96},[87,2709,2710],{"class":2362},"[ ",[87,2712,2496],{"class":147},[87,2714,2715],{"class":2362},"$ACTION",[87,2717,2496],{"class":147},[87,2719,2202],{"class":2366},[87,2721,2722],{"class":147}," \"add\"",[87,2724,2499],{"class":2362},[87,2726,2502],{"class":2366},[87,2728,2729],{"class":213}," exit",[87,2731,2732],{"class":213}," 0\n",[87,2734,2735,2738,2740,2743,2745,2748,2752,2755,2758,2761,2763,2766,2769,2772,2774,2777,2779],{"class":89,"line":102},[87,2736,2737],{"class":2366},"case",[87,2739,2490],{"class":147},[87,2741,2742],{"class":2362},"$DEVICENAME",[87,2744,2496],{"class":147},[87,2746,2747],{"class":2366}," in",[87,2749,2751],{"class":2750},"sA_wV"," eth",[87,2753,2754],{"class":2366},"*|",[87,2756,2757],{"class":2750},"pppoe-",[87,2759,2760],{"class":2366},"*",[87,2762,2107],{"class":2366},[87,2764,2765],{"class":213}," :",[87,2767,2768],{"class":2362}," ;; ",[87,2770,2771],{"class":2366},"*)",[87,2773,2729],{"class":213},[87,2775,2776],{"class":213}," 0",[87,2778,2768],{"class":2362},[87,2780,2781],{"class":2366},"esac\n",[87,2783,2784],{"class":89,"line":108},[87,2785,296],{"emptyLinePlaceholder":295},[87,2787,2788,2790,2792],{"class":89,"line":114},[87,2789,2363],{"class":2362},[87,2791,2367],{"class":2366},[87,2793,2370],{"class":147},[87,2795,2796,2798,2800],{"class":89,"line":314},[87,2797,2375],{"class":2362},[87,2799,2367],{"class":2366},[87,2801,2380],{"class":147},[87,2803,2804,2806,2808,2810,2813,2815,2818,2820,2823,2825,2828,2830],{"class":89,"line":2267},[87,2805,2395],{"class":143},[87,2807,2398],{"class":213},[87,2809,2401],{"class":147},[87,2811,2812],{"class":147}," \"net hook: ",[87,2814,2742],{"class":2362},[87,2816,2817],{"class":147}," ACTION=",[87,2819,2715],{"class":2362},[87,2821,2822],{"class":147}," (mask=",[87,2824,2515],{"class":2362},[87,2826,2827],{"class":147}," flows=",[87,2829,2431],{"class":2362},[87,2831,2410],{"class":147},[87,2833,2834,2836,2838,2840,2842,2844],{"class":89,"line":2278},[87,2835,2419],{"class":143},[87,2837,2422],{"class":213},[87,2839,2425],{"class":213},[87,2841,2428],{"class":147},[87,2843,2431],{"class":2362},[87,2845,2434],{"class":147},[87,2847,2848],{"class":89,"line":2292},[87,2849,296],{"emptyLinePlaceholder":295},[87,2851,2852,2855,2857,2860,2863,2866,2869,2872,2874,2876,2879,2881,2883,2886,2888,2891],{"class":89,"line":2303},[87,2853,2854],{"class":2362},"PARENT",[87,2856,2367],{"class":2366},[87,2858,2859],{"class":147},"\"$(",[87,2861,2862],{"class":143},"basename",[87,2864,2865],{"class":147}," \"$(",[87,2867,2868],{"class":143},"readlink",[87,2870,2871],{"class":213}," -f",[87,2873,2468],{"class":147},[87,2875,2742],{"class":2362},[87,2877,2878],{"class":147},"/lower_",[87,2880,2760],{"class":213},[87,2882,2547],{"class":2366},[87,2884,2885],{"class":147},"/dev/null ",[87,2887,2502],{"class":2366},[87,2889,2890],{"class":213}," true",[87,2892,2893],{"class":147},")\")\"\n",[87,2895,2896,2898,2901,2903,2906,2908,2910,2912,2915,2917,2919,2921],{"class":89,"line":2308},[87,2897,2710],{"class":2362},[87,2899,2900],{"class":2366},"-n",[87,2902,2490],{"class":147},[87,2904,2905],{"class":2362},"$PARENT",[87,2907,2496],{"class":147},[87,2909,2499],{"class":2362},[87,2911,2502],{"class":2366},[87,2913,2914],{"class":2362}," PARENT",[87,2916,2367],{"class":2366},[87,2918,2496],{"class":147},[87,2920,2742],{"class":2362},[87,2922,2434],{"class":147},[87,2924,2925],{"class":89,"line":2314},[87,2926,296],{"emptyLinePlaceholder":295},[87,2928,2929,2932],{"class":89,"line":2530},[87,2930,2931],{"class":143},"apply_one",[87,2933,2934],{"class":2362},"() {\n",[87,2936,2937,2940,2942,2944,2947],{"class":89,"line":2553},[87,2938,2939],{"class":2362},"  IF",[87,2941,2367],{"class":2366},[87,2943,2496],{"class":147},[87,2945,2946],{"class":213},"$1",[87,2948,2434],{"class":147},[87,2950,2951,2953,2956,2958,2961,2964,2967,2970,2973,2975],{"class":89,"line":2559},[87,2952,2460],{"class":2366},[87,2954,2955],{"class":2362}," i ",[87,2957,2449],{"class":2366},[87,2959,2960],{"class":147}," 1",[87,2962,2963],{"class":147}," 2",[87,2965,2966],{"class":147}," 3",[87,2968,2969],{"class":147}," 4",[87,2971,2972],{"class":147}," 5",[87,2974,2477],{"class":2362},[87,2976,2455],{"class":2366},[87,2978,2979,2981,2984,2987,2989,2992,2995],{"class":89,"line":2580},[87,2980,2484],{"class":2362},[87,2982,2983],{"class":2366},"-e",[87,2985,2986],{"class":147}," \"/sys/class/net/",[87,2988,2471],{"class":2362},[87,2990,2991],{"class":147},"/queues/rx-0/rps_cpus\"",[87,2993,2994],{"class":2362}," ] && ",[87,2996,2997],{"class":2366},"break\n",[87,2999,3000,3003],{"class":89,"line":2600},[87,3001,3002],{"class":143},"    sleep",[87,3004,3005],{"class":213}," 1\n",[87,3007,3008],{"class":89,"line":2620},[87,3009,2556],{"class":2366},[87,3011,3012,3014,3016,3018,3021,3023,3026,3028],{"class":89,"line":2625},[87,3013,2460],{"class":2366},[87,3015,2463],{"class":2362},[87,3017,2449],{"class":2366},[87,3019,3020],{"class":147}," /sys/class/net/\"",[87,3022,2471],{"class":2362},[87,3024,3025],{"class":147},"\"/queues/rx-*",[87,3027,2477],{"class":2362},[87,3029,2455],{"class":2366},[87,3031,3032,3034,3036,3038,3040,3043,3045,3047],{"class":89,"line":2631},[87,3033,2484],{"class":2362},[87,3035,2983],{"class":2366},[87,3037,2490],{"class":147},[87,3039,2493],{"class":2362},[87,3041,3042],{"class":147},"/rps_cpus\"",[87,3044,2499],{"class":2362},[87,3046,2502],{"class":2366},[87,3048,2505],{"class":2366},[87,3050,3052,3054,3056,3058,3060,3062,3064,3066],{"class":89,"line":3051},21,[87,3053,2510],{"class":213},[87,3055,2490],{"class":147},[87,3057,2515],{"class":2362},[87,3059,2496],{"class":147},[87,3061,2520],{"class":2366},[87,3063,2490],{"class":147},[87,3065,2493],{"class":2362},[87,3067,2527],{"class":147},[87,3069,3071,3073,3075,3077,3079,3081,3083,3085],{"class":89,"line":3070},22,[87,3072,2510],{"class":213},[87,3074,2535],{"class":213},[87,3076,2520],{"class":2366},[87,3078,2490],{"class":147},[87,3080,2493],{"class":2362},[87,3082,2544],{"class":147},[87,3084,2547],{"class":2366},[87,3086,2550],{"class":147},[87,3088,3090],{"class":89,"line":3089},23,[87,3091,2556],{"class":2366},[87,3093,3095,3097,3099,3101,3103,3105,3108,3110],{"class":89,"line":3094},24,[87,3096,2460],{"class":2366},[87,3098,2564],{"class":2362},[87,3100,2449],{"class":2366},[87,3102,3020],{"class":147},[87,3104,2471],{"class":2362},[87,3106,3107],{"class":147},"\"/queues/tx-*",[87,3109,2477],{"class":2362},[87,3111,2455],{"class":2366},[87,3113,3115,3117,3119,3121,3123,3126,3128,3130],{"class":89,"line":3114},25,[87,3116,2484],{"class":2362},[87,3118,2983],{"class":2366},[87,3120,2490],{"class":147},[87,3122,2589],{"class":2362},[87,3124,3125],{"class":147},"/xps_cpus\"",[87,3127,2499],{"class":2362},[87,3129,2502],{"class":2366},[87,3131,2505],{"class":2366},[87,3133,3135,3137,3139,3141,3143,3145,3147,3149],{"class":89,"line":3134},26,[87,3136,2510],{"class":213},[87,3138,2490],{"class":147},[87,3140,2515],{"class":2362},[87,3142,2496],{"class":147},[87,3144,2520],{"class":2366},[87,3146,2490],{"class":147},[87,3148,2589],{"class":2362},[87,3150,2617],{"class":147},[87,3152,3154],{"class":89,"line":3153},27,[87,3155,2556],{"class":2366},[87,3157,3159],{"class":89,"line":3158},28,[87,3160,3161],{"class":2362},"}\n",[87,3163,3165],{"class":89,"line":3164},29,[87,3166,296],{"emptyLinePlaceholder":295},[87,3168,3170,3172,3174,3176],{"class":89,"line":3169},30,[87,3171,2931],{"class":143},[87,3173,2490],{"class":147},[87,3175,2905],{"class":2362},[87,3177,2434],{"class":147},[87,3179,3181,3183,3185,3187],{"class":89,"line":3180},31,[87,3182,2931],{"class":143},[87,3184,2490],{"class":147},[87,3186,2742],{"class":2362},[87,3188,2434],{"class":147},[11,3190,2652,3191],{},[15,3192,2655],{},[77,3194,3196],{"className":134,"code":3195,"language":136,"meta":82,"style":82},"chmod +x /etc/hotplug.d/net/99-optimize-network\n",[84,3197,3198],{"__ignoreMap":82},[87,3199,3200,3202,3204],{"class":89,"line":90},[87,3201,2665],{"class":143},[87,3203,2668],{"class":147},[87,3205,3206],{"class":147}," /etc/hotplug.d/net/99-optimize-network\n",[364,3208],{},[61,3210,3212,3213],{"id":3211},"_4️⃣-hook-iface-fallback-su-evento-ifup","🪝 4️⃣  Hook IFACE – Fallback su evento ",[84,3214,3215],{},"ifup",[11,3217,2181,3218],{},[15,3219,3220],{},[84,3221,3222],{},"/etc/hotplug.d/iface/99-rpsxps",[11,3224,3225],{},"Serve come “cintura di sicurezza” in caso di ricreazione PPPoE o WAN da script esterni (es. DDNS)",[77,3227,3229],{"className":134,"code":3228,"language":136,"meta":82,"style":82},"#!/bin/sh\n[ \"$ACTION\" = \"ifup\" ] || exit 0\n\ncase \"$INTERFACE\" in\n  wan|lan)\n    /bin/sh -c \"sleep 1; /usr/local/sbin/apply-rpsxps.sh\"\n    ;;\nesac\n",[84,3230,3231,3235,3258,3262,3276,3290,3301,3306],{"__ignoreMap":82},[87,3232,3233],{"class":89,"line":90},[87,3234,2357],{"class":151},[87,3236,3237,3239,3241,3243,3245,3247,3250,3252,3254,3256],{"class":89,"line":96},[87,3238,2710],{"class":2362},[87,3240,2496],{"class":147},[87,3242,2715],{"class":2362},[87,3244,2496],{"class":147},[87,3246,2202],{"class":2366},[87,3248,3249],{"class":147}," \"ifup\"",[87,3251,2499],{"class":2362},[87,3253,2502],{"class":2366},[87,3255,2729],{"class":213},[87,3257,2732],{"class":213},[87,3259,3260],{"class":89,"line":102},[87,3261,296],{"emptyLinePlaceholder":295},[87,3263,3264,3266,3268,3271,3273],{"class":89,"line":108},[87,3265,2737],{"class":2366},[87,3267,2490],{"class":147},[87,3269,3270],{"class":2362},"$INTERFACE",[87,3272,2496],{"class":147},[87,3274,3275],{"class":2366}," in\n",[87,3277,3278,3281,3284,3287],{"class":89,"line":114},[87,3279,3280],{"class":2750},"  wan",[87,3282,3283],{"class":2366},"|",[87,3285,3286],{"class":2750},"lan",[87,3288,3289],{"class":2366},")\n",[87,3291,3292,3295,3298],{"class":89,"line":314},[87,3293,3294],{"class":143},"    /bin/sh",[87,3296,3297],{"class":213}," -c",[87,3299,3300],{"class":147}," \"sleep 1; /usr/local/sbin/apply-rpsxps.sh\"\n",[87,3302,3303],{"class":89,"line":2267},[87,3304,3305],{"class":2362},"    ;;\n",[87,3307,3308],{"class":89,"line":2278},[87,3309,2781],{"class":2366},[11,3311,2652,3312],{},[15,3313,2655],{},[77,3315,3317],{"className":134,"code":3316,"language":136,"meta":82,"style":82},"chmod +x /etc/hotplug.d/iface/99-rpsxps\n",[84,3318,3319],{"__ignoreMap":82},[87,3320,3321,3323,3325],{"class":89,"line":90},[87,3322,2665],{"class":143},[87,3324,2668],{"class":147},[87,3326,3327],{"class":147}," /etc/hotplug.d/iface/99-rpsxps\n",[364,3329],{},[61,3331,3333],{"id":3332},"_5️⃣-esecuzione-al-boot-failsafe","🚀 5️⃣  Esecuzione al boot (failsafe)",[11,3335,2181,3336],{},[15,3337,3338],{},[84,3339,3340],{},"/etc/rc.local",[11,3342,3343],{},"Garantisce che lo script venga lanciato anche all’avvio completo del sistema (dopo init)",[77,3345,3347],{"className":134,"code":3346,"language":136,"meta":82,"style":82},"/usr/local/sbin/apply-rpsxps.sh || true\nexit 0\n",[84,3348,3349,3359],{"__ignoreMap":82},[87,3350,3351,3353,3356],{"class":89,"line":90},[87,3352,2335],{"class":143},[87,3354,3355],{"class":2366}," ||",[87,3357,3358],{"class":213}," true\n",[87,3360,3361,3364],{"class":89,"line":96},[87,3362,3363],{"class":213},"exit",[87,3365,2732],{"class":213},[364,3367],{},[61,3369,3371],{"id":3370},"_6️⃣-opzionale-cpu-governor","🧠 6️⃣  (Opzionale) CPU governor",[11,3373,3374,3375,3378,3379,3382],{},"Se vuoi forzare il governor ",[15,3376,3377],{},"conservative"," o ",[15,3380,3381],{},"performance"," all’avvio:",[11,3384,2181,3385,3389,3390,2107],{},[15,3386,3387],{},[84,3388,3340],{}," (appendi sotto la riga ",[84,3391,3392],{},"apply-rpsxps.sh",[77,3394,3396],{"className":134,"code":3395,"language":136,"meta":82,"style":82},"for g in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do\n    echo conservative > \"$g\"\ndone\n",[84,3397,3398,3414,3430],{"__ignoreMap":82},[87,3399,3400,3402,3405,3407,3410,3412],{"class":89,"line":90},[87,3401,2443],{"class":2366},[87,3403,3404],{"class":2362}," g ",[87,3406,2449],{"class":2366},[87,3408,3409],{"class":147}," /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor",[87,3411,2477],{"class":2362},[87,3413,2455],{"class":2366},[87,3415,3416,3418,3421,3423,3425,3428],{"class":89,"line":96},[87,3417,2510],{"class":213},[87,3419,3420],{"class":147}," conservative",[87,3422,2520],{"class":2366},[87,3424,2490],{"class":147},[87,3426,3427],{"class":2362},"$g",[87,3429,2434],{"class":147},[87,3431,3432],{"class":89,"line":102},[87,3433,2628],{"class":2366},[364,3435],{},[61,3437,3439],{"id":3438},"_7️⃣-verifica-post-boot","🧾 7️⃣  Verifica post-boot",[11,3441,3442],{},"Comandi di controllo:",[77,3444,3446],{"className":134,"code":3445,"language":136,"meta":82,"style":82},"logread -e rpsxps | tail -n 20\ngrep . /sys/class/net/eth{0,1}/queues/{rx,tx}-*/rps_cpus\nsysctl net.core.rps_sock_flow_entries\n",[84,3447,3448,3470,3486],{"__ignoreMap":82},[87,3449,3450,3453,3456,3458,3461,3464,3467],{"class":89,"line":90},[87,3451,3452],{"class":143},"logread",[87,3454,3455],{"class":213}," -e",[87,3457,2401],{"class":147},[87,3459,3460],{"class":2366}," |",[87,3462,3463],{"class":143}," tail",[87,3465,3466],{"class":213}," -n",[87,3468,3469],{"class":213}," 20\n",[87,3471,3472,3475,3478,3481,3483],{"class":89,"line":96},[87,3473,3474],{"class":143},"grep",[87,3476,3477],{"class":147}," .",[87,3479,3480],{"class":147}," /sys/class/net/eth{0,1}/queues/{rx,tx}-",[87,3482,2760],{"class":213},[87,3484,3485],{"class":147},"/rps_cpus\n",[87,3487,3488,3490],{"class":89,"line":102},[87,3489,2419],{"class":143},[87,3491,3492],{"class":147}," net.core.rps_sock_flow_entries\n",[11,3494,3495],{},"Output atteso:",[77,3497,3502],{"className":3498,"code":3500,"language":3501},[3499],"language-text","rpsxps: net hook: eth0.835 ACTION=add ...\nrpsxps: net hook: pppoe-wan ACTION=add ...\n...\n/sys/class/net/eth0.835/queues/rx-0/rps_cpus: ff\n/sys/class/net/eth0/queues/tx-0/xps_cpus: ff\n/sys/class/net/eth1/queues/tx-0/xps_cpus: ff\nnet.core.rps_sock_flow_entries = 65536\n","text",[84,3503,3500],{"__ignoreMap":82},[364,3505],{},[24,3507,3509],{"id":3508},"risultati-finali","🚀 Risultati finali",[11,3511,3512],{},"Dopo il reboot e una verifica completa dei parametri, il risultato è stato spettacolare:",[1990,3514,3515,3525],{},[1993,3516,3517],{},[1996,3518,3519,3521,3523],{},[1999,3520,2001],{},[1999,3522,2004],{},[1999,3524,2007],{},[2009,3526,3527,3538,3548],{},[1996,3528,3529,3534,3536],{},[2014,3530,3531],{},[15,3532,3533],{},"Before",[2014,3535,2021],{},[2014,3537,2024],{},[1996,3539,3540,3544,3546],{},[2014,3541,3542],{},[15,3543,2145],{},[2014,3545,2148],{},[2014,3547,2151],{},[1996,3549,3550,3555,3561],{},[2014,3551,3552],{},[15,3553,3554],{},"Tuning finale",[2014,3556,3557,3558],{},"🟢 ",[15,3559,3560],{},"2162 Mbps",[2014,3562,3557,3563],{},[15,3564,3565],{},"1038 Mbps",[24,3567,601],{"id":600},[11,3569,3570,3571,3573],{},"Il ",[15,3572,1917],{}," è un hardware eccezionale, ma per sfruttarlo al massimo serve una configurazione mirata.\nDi default, OpenWrt/FriendlyWrt non imposta:",[29,3575,3576,3579],{},[32,3577,3578],{},"IRQ affinity efficiente",[32,3580,3581],{},"RPS/XPS su tutti i core",[11,3583,3584,3585,3588,3589,3592,3593,398],{},"Con pochi accorgimenti, questo piccolo router passa da ",[15,3586,3587],{},"midrange"," a ",[15,3590,3591],{},"full 2.5 Gbps router",". In barba a cosa si possa pensare dei ",[662,3594,3595],{},"soft router",[400,3597,3598],{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sA_wV, html code.shiki .sA_wV{--shiki-default:#032F62;--shiki-dark:#DBEDFF}",{"title":82,"searchDepth":96,"depth":96,"links":3600},[3601,3602,3603,3604,3607,3617,3618],{"id":1934,"depth":96,"text":1935},{"id":1975,"depth":96,"text":1976},{"id":2047,"depth":96,"text":2048},{"id":2088,"depth":96,"text":2089,"children":3605},[3606],{"id":2123,"depth":102,"text":2124},{"id":2162,"depth":96,"text":2163,"children":3608},[3609,3610,3611,3612,3614,3615,3616],{"id":2177,"depth":102,"text":2178},{"id":2327,"depth":102,"text":2328},{"id":2676,"depth":102,"text":2677},{"id":3211,"depth":102,"text":3613},"🪝 4️⃣  Hook IFACE – Fallback su evento ifup",{"id":3332,"depth":102,"text":3333},{"id":3370,"depth":102,"text":3371},{"id":3438,"depth":102,"text":3439},{"id":3508,"depth":96,"text":3509},{"id":600,"depth":96,"text":601},[3620,3621,3622],"networking","devops","hardware","https://i2.wp.com/enricodeleo.s3.eu-south-1.amazonaws.com/images/nanopi-r76s-performance.png","2025-10-05T09:00:00.000Z","Come ho ottimizzato il NanoPi R76S con OpenWrt per passare da 600 Mbps a oltre 2 Gbps reali, sistemando IRQ, RPS/XPS e CPU governor per sfruttare al massimo il SoC Rockchip RK3576.",{},"/nanopi-r76s-router-2-5gbps-performance-speed-boost",{"title":1905,"description":3625},"nanopi-r76s-router-2-5gbps-performance-speed-boost",[3631,3632,3633,3634,3381,3635],"openwrt","nanopi","router","linux","tuning","RdJAYi52JTNcgoaJqjoKg-oDyw808HqOn6zwZojyAG8",{"id":3638,"title":3639,"body":3640,"categories":3785,"coverImage":3786,"date":3787,"description":3788,"extension":420,"meta":3789,"navigation":295,"path":3790,"seo":3791,"stem":3792,"sticky":1005,"tags":3793,"__hash__":3800},"articles/aisa-assistente-vendite-ai.md","AISA: Ho creato l'assistente alle vendite AI che dialoga con i tuoi clienti e potenzia le conversioni",{"type":8,"value":3641,"toc":3778},[3642,3651,3657,3664,3668,3674,3677,3731,3735,3745,3748,3752,3755,3758,3762],[11,3643,3644],{},[662,3645,3646,3647,3650],{},"Nel mio percorso di imprenditore e consulente digitale, ho sempre cercato soluzioni in grado non solo di risolvere problemi, ma di anticiparli. Oggi vi presento il mio ultimo progetto, ",[15,3648,3649],{},"AISA (AI Sales Assistant)",", un passo avanti nell'evoluzione dell'interazione tra brand e cliente, nato per superare i limiti dei chatbot tradizionali.",[11,3652,3653,3654],{},"Se gestisci un e-commerce o un qualsiasi business con una presenza online, sai bene quanto sia cruciale l'assistenza clienti. Spesso, però, i chatbot tradizionali sono una fonte di frustrazione, incapaci di comprendere le reali esigenze dell'utente. ",[15,3655,3656],{},"La tecnologia dovrebbe essere un acceleratore, non un ostacolo.",[11,3658,3659,3660,3663],{},"È da questa consapevolezza che nasce AISA. Non si tratta dell'ennesimo chatbot, ma di un vero e proprio ",[15,3661,3662],{},"agente AI"," pensato per le vendite, capace di integrarsi nel tessuto digitale di qualsiasi azienda e di agire come un venditore esperto, sempre disponibile.",[24,3665,3667],{"id":3666},"cosa-rende-aisa-diverso","Cosa rende AISA diverso?",[11,3669,3670,3671,398],{},"AISA è stato progettato per essere il punto di contatto intelligente e proattivo con la tua clientela. Il suo obiettivo non è solo rispondere, ma ",[15,3672,3673],{},"vendere e assistere in modo proattivo",[11,3675,3676],{},"Ecco le sue funzionalità chiave:",[29,3678,3679,3688,3694,3711,3721],{},[32,3680,3681,3684,3685,398],{},[15,3682,3683],{},"Dialogo multicanale",": Risponde ai clienti sul tuo sito web, su una landing page, all'interno della tua app e persino tramite ",[15,3686,3687],{},"WhatsApp",[32,3689,3690,3693],{},[15,3691,3692],{},"Tone of Voice personalizzato",": AISA impara e adotta il tono di voce del tuo brand, per un'esperienza utente sempre coerente con la tua identità.",[32,3695,3696,3699,3700,3703,3704,3707,3708,398],{},[15,3697,3698],{},"Base di conoscenza flessibile",": La sua intelligenza si nutre delle informazioni che già possiedi. Supportiamo l'indicizzazione di ",[15,3701,3702],{},"sitemap XML",", il ",[15,3705,3706],{},"crawling del sito",", e l'analisi di ",[15,3709,3710],{},"PDF, testi e tracciati di prodotto",[32,3712,3713,3716,3717,3720],{},[15,3714,3715],{},"Widget di prodotto interattivi",": Quando consiglia un articolo, genera in automatico un ",[15,3718,3719],{},"widget"," che mostra immagine, prezzo, sconto e pulsante \"Aggiungi al carrello\", semplificando il percorso d'acquisto.",[32,3722,3723,3726,3727,3730],{},[15,3724,3725],{},"Integrazione \"Agentic\"",": Grazie alla sua capacità di ",[15,3728,3729],{},"invocare i servizi web del brand",", può aggiornare lo stato di un ordine o reperire informazioni specifiche su un cliente, agendo come un vero agente autonomo.",[24,3732,3734],{"id":3733},"più-di-un-chatbot-un-partner-per-la-crescita","Più di un chatbot, un partner per la crescita",[11,3736,3737,3738,3741,3742,398],{},"La differenza è sostanziale. Mentre un chatbot segue un flusso rigido, AISA offre risposte dinamiche, impara dalle interazioni e personalizza i consigli. I primi dati raccolti sono incredibilmente promettenti, con un ",[15,3739,3740],{},"aumento medio del tasso di conversione dell'8%"," e una ",[15,3743,3744],{},"riduzione del 32% delle richieste di assistenza manuale",[11,3746,3747],{},"È la soluzione ideale per chi vuole fare un salto di qualità nella gestione delle vendite online, trasformando l'assistenza clienti da centro di costo a motore di ricavi.",[24,3749,3751],{"id":3750},"conclusione-un-nuovo-standard-per-linterazione-online","Conclusione: un nuovo standard per l'interazione online",[11,3753,3754],{},"AISA rappresenta la mia visione di come l'intelligenza artificiale possa essere applicata in modo concreto e profittevole nel mondo del marketing e delle vendite. È uno strumento potente, pensato per chi, come me, crede che la tecnologia debba lavorare al nostro fianco per creare valore reale.",[11,3756,3757],{},"Sei pronto a scoprire come AISA può trasformare la tua interazione con i clienti e spingere le tue vendite?",[61,3759,3761],{"id":3760},"vuoi-saperne-di-più","Vuoi saperne di più?",[11,3763,3764,3765,3772,3773,3777],{},"Visita la pagina ufficiale del progetto ",[15,3766,3767],{},[377,3768,3771],{"href":3769,"rel":3770},"https://www.autocust.it/sales-assistant-ai",[381],"AI Sales Assistant"," o contattami ",[377,3774,3776],{"href":625,"rel":3775},[381],"sul mio profilo LinkedIn"," per discutere di come integrare AISA nel tuo business.",{"title":82,"searchDepth":96,"depth":96,"links":3779},[3780,3781,3782],{"id":3666,"depth":96,"text":3667},{"id":3733,"depth":96,"text":3734},{"id":3750,"depth":96,"text":3751,"children":3783},[3784],{"id":3760,"depth":102,"text":3761},[1007,414],"https://i2.wp.com/enricodeleo.s3.eu-south-1.amazonaws.com/images/aisa.png","2025-07-27T18:45:00.000Z","Vi presento AISA, il mio nuovo progetto: un assistente vendite basato su AI che trasforma l'interazione con i clienti, aumentando le conversioni e offrendo un'esperienza utente senza precedenti.",{},"/aisa-assistente-vendite-ai",{"title":3639,"description":3788},"aisa-assistente-vendite-ai",[3794,3795,3796,3797,3798,3799],"aisa","ai-sales-assistant","intelligenza-artificiale","marketing-automation","ecommerce","chatbot","nJceN4OmS8f3dobB-ukZzdhUbCaRXDBbFCKoZmQ_KS8",1777303094564]