[{"data":1,"prerenderedAt":2447},["ShallowReactive",2],{"content-/cperez/2026-07-16/rebuild-vs-modernize-software-cfo-guide":3},{"article":4,"all":1454},{"_path":5,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"title":9,"description":10,"publishDate":6,"image":11,"author":12,"tags":15,"excerpt":10,"body":21,"_type":1448,"_id":1449,"_source":1450,"_file":1451,"_stem":1452,"_extension":1453},"/cperez/2026-07-16/rebuild-vs-modernize-software-cfo-guide","2026-07-16",false,"","Rebuild or Modernize? A Guide to Making the Right Software Investment","Every aging software system eventually reaches a financial decision point.","/cperez/2026-07-16/img/rebuild-vs-modernize-software-cfo-guide.jpg",{"name":13,"user":14},"Carlos Perez","cperez",[16,17,18,19,20],"modernization","legacy migration","tech debt","application modernization","legacy software",{"type":22,"children":23,"toc":1402},"root",[24,31,36,41,50,55,60,65,70,77,89,100,105,113,118,123,128,136,142,147,152,168,173,178,183,194,199,205,210,215,220,239,244,251,256,261,266,272,277,282,287,292,297,303,314,319,324,330,335,340,345,351,356,361,373,378,383,388,393,398,403,408,414,419,424,430,435,440,445,450,456,461,466,471,477,482,487,492,497,503,508,513,519,524,529,534,540,545,550,556,561,566,571,582,588,593,598,603,609,614,619,630,636,641,646,651,657,662,673,678,684,689,694,700,705,710,715,720,725,730,735,740,746,751,756,761,766,772,777,782,787,827,832,838,843,848,877,882,887,893,898,903,908,913,918,924,929,934,939,944,949,955,960,965,970,975,980,985,990,996,1001,1006,1011,1016,1021,1026,1032,1037,1075,1080,1118,1123,1151,1156,1162,1167,1172,1177,1220,1225,1230,1236,1241,1246,1251,1256,1261,1272,1278,1283,1288,1293,1298,1306,1311,1316,1321,1325,1331,1337,1342,1348,1353,1359,1364,1370,1375,1381,1386,1392,1397],{"type":25,"tag":26,"props":27,"children":28},"element","p",{},[29],{"type":30,"value":10},"text",{"type":25,"tag":26,"props":32,"children":33},{},[34],{"type":30,"value":35},"The business depends on it. Teams complain about it. Customers may never see it directly, but they feel its limits in slower service, delayed releases, clunky workflows, inconsistent data, or rising support costs. Engineering says the architecture is holding the company back. Operations says the system is too important to disrupt. Finance sees the maintenance spend growing, but also knows that “let’s rebuild it from scratch” can become an expensive, open-ended bet.",{"type":25,"tag":26,"props":37,"children":38},{},[39],{"type":30,"value":40},"For CFOs, the core dilemma comes down to this:",{"type":25,"tag":26,"props":42,"children":43},{},[44],{"type":25,"tag":45,"props":46,"children":47},"strong",{},[48],{"type":30,"value":49},"Should we rebuild this software, or modernize what we already have?",{"type":25,"tag":26,"props":51,"children":52},{},[53],{"type":30,"value":54},"The answer is rarely obvious. A full rebuild can sound clean and decisive, but it also carries serious cost, timeline concerns, and adoption risk. Modernization can preserve valuable business logic and reduce disruption, but it may not go far enough if the foundation no longer supports where the business needs to go.",{"type":25,"tag":26,"props":56,"children":57},{},[58],{"type":30,"value":59},"This isn’t just a technology decision; it’s a capital allocation decision.",{"type":25,"tag":26,"props":61,"children":62},{},[63],{"type":30,"value":64},"AI is also changing the economics of this decision. The early work of modernization, understanding legacy code, surfacing undocumented business logic, identifying dependencies, and mapping a phased path forward, has historically required a lot of manual analysis. Modern AI tools can accelerate parts of that work, giving teams a faster and clearer view of what they are dealing with. That does not replace experienced engineers, especially when business context, architecture, security, and tradeoffs matter. But it can change the financial equation. For CFOs evaluating whether to rebuild or modernize, AI may reduce discovery time, improve visibility into hidden complexity, and make phased modernization a more practical option than it would have been a few years ago.",{"type":25,"tag":26,"props":66,"children":67},{},[68],{"type":30,"value":69},"For CFOs, the goal is to understand which path creates the best risk-adjusted return: lower operating costs, faster delivery, stronger security, better reporting, improved customer experience, and more flexibility for future growth.",{"type":25,"tag":71,"props":72,"children":74},"h3",{"id":73},"rebuild-vs-modernize-whats-the-difference",[75],{"type":30,"value":76},"Rebuild vs. Modernize: What’s the Difference?",{"type":25,"tag":26,"props":78,"children":79},{},[80,82,87],{"type":30,"value":81},"A ",{"type":25,"tag":45,"props":83,"children":84},{},[85],{"type":30,"value":86},"software rebuild",{"type":30,"value":88}," means replacing an existing application with a new system, usually built from the ground up. The team may reuse requirements, workflows, data models, or integrations, but the core application is recreated on a new technical foundation.",{"type":25,"tag":26,"props":90,"children":91},{},[92,93,98],{"type":30,"value":81},{"type":25,"tag":45,"props":94,"children":95},{},[96],{"type":30,"value":97},"software modernization",{"type":30,"value":99}," effort improves the existing system without replacing everything at once. That can include refactoring code, updating infrastructure, improving security, moving selected workloads to the cloud, replacing outdated components, exposing APIs, improving observability, redesigning workflows, or gradually separating a monolithic system into more flexible services.",{"type":25,"tag":26,"props":101,"children":102},{},[103],{"type":30,"value":104},"Put simply:",{"type":25,"tag":26,"props":106,"children":107},{},[108],{"type":25,"tag":45,"props":109,"children":110},{},[111],{"type":30,"value":112},"Rebuilding replaces the system. Modernizing evolves the system.",{"type":25,"tag":26,"props":114,"children":115},{},[116],{"type":30,"value":117},"But in practice, the line is not always clean. Many successful software investments are hybrids. A company may modernize the parts of a system that still work while rebuilding the pieces that create the most cost, risk, or strategic constraint.",{"type":25,"tag":26,"props":119,"children":120},{},[121],{"type":30,"value":122},"For CFOs, the better question is not “Which option is more modern?”",{"type":25,"tag":26,"props":124,"children":125},{},[126],{"type":30,"value":127},"It is:",{"type":25,"tag":26,"props":129,"children":130},{},[131],{"type":25,"tag":45,"props":132,"children":133},{},[134],{"type":30,"value":135},"Which investment path produces measurable business value without creating unnecessary operational risk?",{"type":25,"tag":71,"props":137,"children":139},{"id":138},"why-legacy-systems-survive-so-long",[140],{"type":30,"value":141},"Why Legacy Systems Survive So Long",{"type":25,"tag":26,"props":143,"children":144},{},[145],{"type":30,"value":146},"It is easy to assume legacy systems stick around because organizations are resistant to change.",{"type":25,"tag":26,"props":148,"children":149},{},[150],{"type":30,"value":151},"More often, they survive because they are doing something important.",{"type":25,"tag":26,"props":153,"children":154},{},[155,157,166],{"type":30,"value":156},"Legacy systems often support critical business operations, contain years of accumulated business logic, and encode workflows that may not be documented anywhere else. Teams rely on them every day. Customers may interact with them directly or depend on processes they enable behind the scenes. The longer a system has been running, the more deeply it tends to connect with the organization around it. (",{"type":25,"tag":158,"props":159,"children":163},"a",{"href":160,"rel":161},"https://artandlogic.com/newsletters/what-modernizing-legacy-systems-actually-means-in-practice/",[162],"nofollow",[164],{"type":30,"value":165},"Art+Logic",{"type":30,"value":167},")",{"type":25,"tag":26,"props":169,"children":170},{},[171],{"type":30,"value":172},"That is what makes the rebuild-versus-modernize decision difficult.",{"type":25,"tag":26,"props":174,"children":175},{},[176],{"type":30,"value":177},"You are rarely replacing “just software.” You are changing a network of assumptions, workflows, reporting habits, integrations, exceptions, and institutional knowledge that has evolved.",{"type":25,"tag":26,"props":179,"children":180},{},[181],{"type":30,"value":182},"That is also why a rebuild can fail even when the new technology is better.",{"type":25,"tag":26,"props":184,"children":185},{},[186,188,193],{"type":30,"value":187},"If the project underestimates the business knowledge embedded in the existing system, teams may discover undocumented workflows, edge cases, reporting requirements, and integrations after development is already underway. As a result, costs increase, timelines stretch, and confidence erodes. (",{"type":25,"tag":158,"props":189,"children":191},{"href":160,"rel":190},[162],[192],{"type":30,"value":165},{"type":30,"value":167},{"type":25,"tag":26,"props":195,"children":196},{},[197],{"type":30,"value":198},"For CFOs, the lesson is simple: before funding a rebuild, make sure the organization understands what the current system actually does.",{"type":25,"tag":71,"props":200,"children":202},{"id":201},"the-hidden-cost-of-keeping-it-running",[203],{"type":30,"value":204},"The Hidden Cost of “Keeping It Running”",{"type":25,"tag":26,"props":206,"children":207},{},[208],{"type":30,"value":209},"Legacy software often looks cheaper than it is.",{"type":25,"tag":26,"props":211,"children":212},{},[213],{"type":30,"value":214},"On paper, the system is already built. The original investment is behind you. The team knows how to operate it. Customers are using it. Replacing it looks expensive.",{"type":25,"tag":26,"props":216,"children":217},{},[218],{"type":30,"value":219},"But maintaining an aging system can create a compounding drag on the business.",{"type":25,"tag":26,"props":221,"children":222},{},[223,225,230,232,238],{"type":30,"value":224},"Art+Logic has described this as a ",{"type":25,"tag":45,"props":226,"children":227},{},[228],{"type":30,"value":229},"velocity tax",{"type":30,"value":231},": when small changes take too long, QA cycles drag, deployments are slow, and teams spend more time working around the system than improving it. (",{"type":25,"tag":158,"props":233,"children":236},{"href":234,"rel":235},"https://artandlogic.com/newsletters/is-your-legacy-system-holding-you-back/",[162],[237],{"type":30,"value":165},{"type":30,"value":167},{"type":25,"tag":26,"props":240,"children":241},{},[242],{"type":30,"value":243},"For a CFO, that tax shows up in several ways.",{"type":25,"tag":245,"props":246,"children":248},"h4",{"id":247},"maintenance-cost",[249],{"type":30,"value":250},"Maintenance Cost",{"type":25,"tag":26,"props":252,"children":253},{},[254],{"type":30,"value":255},"Older systems often require more effort for routine changes. Engineers spend time understanding fragile code, avoiding side effects, patching outdated dependencies, or working around architectural constraints.",{"type":25,"tag":26,"props":257,"children":258},{},[259],{"type":30,"value":260},"That effort may be classified as a normal development expense, but financially it behaves more like debt service.",{"type":25,"tag":26,"props":262,"children":263},{},[264],{"type":30,"value":265},"The business keeps paying interest on past decisions.",{"type":25,"tag":245,"props":267,"children":269},{"id":268},"opportunity-cost",[270],{"type":30,"value":271},"Opportunity Cost",{"type":25,"tag":26,"props":273,"children":274},{},[275],{"type":30,"value":276},"When every product improvement takes too long, the company loses speed.",{"type":25,"tag":26,"props":278,"children":279},{},[280],{"type":30,"value":281},"New pricing models, customer features, integrations, automation initiatives, compliance updates, and reporting improvements may all be delayed because the software cannot support change efficiently.",{"type":25,"tag":26,"props":283,"children":284},{},[285],{"type":30,"value":286},"This is where legacy systems become a growth constraint.",{"type":25,"tag":26,"props":288,"children":289},{},[290],{"type":30,"value":291},"The issue is not only what the system costs.",{"type":25,"tag":26,"props":293,"children":294},{},[295],{"type":30,"value":296},"It is what the system prevents.",{"type":25,"tag":245,"props":298,"children":300},{"id":299},"talent-cost",[301],{"type":30,"value":302},"Talent Cost",{"type":25,"tag":26,"props":304,"children":305},{},[306,308,313],{"type":30,"value":307},"Outdated systems can make it harder to hire and retain strong technical talent. Developers generally want modern tooling, healthy development practices, and systems where they can make meaningful progress. If the stack feels brittle or dated, the company may narrow its talent pool and increase retention risk. (",{"type":25,"tag":158,"props":309,"children":311},{"href":234,"rel":310},[162],[312],{"type":30,"value":165},{"type":30,"value":167},{"type":25,"tag":26,"props":315,"children":316},{},[317],{"type":30,"value":318},"Even when the current team is excellent, institutional knowledge can become concentrated in a few people.",{"type":25,"tag":26,"props":320,"children":321},{},[322],{"type":30,"value":323},"That creates key-person risk.",{"type":25,"tag":245,"props":325,"children":327},{"id":326},"risk-cost",[328],{"type":30,"value":329},"Risk Cost",{"type":25,"tag":26,"props":331,"children":332},{},[333],{"type":30,"value":334},"Aging software can carry security, compliance, availability, and data integrity risks. Outdated frameworks, fragile integrations, limited automated testing, and poor observability can increase the likelihood and impact of incidents.",{"type":25,"tag":26,"props":336,"children":337},{},[338],{"type":30,"value":339},"The cost of a system failure is not just remediation.",{"type":25,"tag":26,"props":341,"children":342},{},[343],{"type":30,"value":344},"It can include lost revenue, SLA penalties, customer churn, operational disruption, audit exposure, reputational damage, and executive distraction.",{"type":25,"tag":71,"props":346,"children":348},{"id":347},"technical-debt-is-a-business-discipline",[349],{"type":30,"value":350},"Technical Debt Is a Business Discipline",{"type":25,"tag":26,"props":352,"children":353},{},[354],{"type":30,"value":355},"Technical debt is often discussed as an engineering issue: messy code, rushed patches, outdated frameworks, or brittle architecture.",{"type":25,"tag":26,"props":357,"children":358},{},[359],{"type":30,"value":360},"But debt in software rarely lives only in the codebase.",{"type":25,"tag":26,"props":362,"children":363},{},[364,366,372],{"type":30,"value":365},"It also accumulates in product decisions, design shortcuts, release processes, documentation gaps, and team culture. Product debt can create bloated features that do not serve real user needs. Design debt can create fragmented workflows and adoption friction. Process debt can turn small fixes into weeks of untangling. Cultural debt can normalize short-term wins at the expense of long-term stability. (",{"type":25,"tag":158,"props":367,"children":370},{"href":368,"rel":369},"https://artandlogic.com/newsletters/tech-debt-isnt-just-technical/",[162],[371],{"type":30,"value":165},{"type":30,"value":167},{"type":25,"tag":26,"props":374,"children":375},{},[376],{"type":30,"value":377},"That matters for CFOs because software debt behaves a lot like financial debt.",{"type":25,"tag":26,"props":379,"children":380},{},[381],{"type":30,"value":382},"Some debt is intentional and useful. A company may take a shortcut to reach the market faster, validate demand, or satisfy an urgent customer need. That can be a rational tradeoff.",{"type":25,"tag":26,"props":384,"children":385},{},[386],{"type":30,"value":387},"The problem is unmanaged debt.",{"type":25,"tag":26,"props":389,"children":390},{},[391],{"type":30,"value":392},"If the business keeps deferring repayment, the cost compounds. Teams move slower. Customer experience suffers. Support costs rise. Reporting becomes less trustworthy. Investors and stakeholders lose confidence in the company’s ability to adapt.",{"type":25,"tag":26,"props":394,"children":395},{},[396],{"type":30,"value":397},"The goal is not to eliminate all technical debt.",{"type":25,"tag":26,"props":399,"children":400},{},[401],{"type":30,"value":402},"The goal is to know which debt you are carrying, what it is costing, and when it needs to be paid down.",{"type":25,"tag":26,"props":404,"children":405},{},[406],{"type":30,"value":407},"That makes rebuilds and modernization efforts easier to evaluate. They are not abstract “technology upgrades.” They are debt management strategies.",{"type":25,"tag":71,"props":409,"children":411},{"id":410},"when-a-rebuild-makes-financial-sense",[412],{"type":30,"value":413},"When a Rebuild Makes Financial Sense",{"type":25,"tag":26,"props":415,"children":416},{},[417],{"type":30,"value":418},"A full rebuild is not automatically wrong. In some situations, it is the responsible choice.",{"type":25,"tag":26,"props":420,"children":421},{},[422],{"type":30,"value":423},"A rebuild may make sense when the existing system no longer matches the business model, customer expectations, operational needs, or strategic direction of the company.",{"type":25,"tag":71,"props":425,"children":427},{"id":426},"_1-the-current-system-cannot-support-the-future-business",[428],{"type":30,"value":429},"1. The Current System Cannot Support the Future Business",{"type":25,"tag":26,"props":431,"children":432},{},[433],{"type":30,"value":434},"If the company is entering new markets, changing pricing models, scaling transaction volume, adding digital services, preparing for M&A, or shifting from internal tooling to customer-facing software, the old architecture may not be fit for purpose.",{"type":25,"tag":26,"props":436,"children":437},{},[438],{"type":30,"value":439},"A system designed for one stage of the business can become a liability in the next.",{"type":25,"tag":26,"props":441,"children":442},{},[443],{"type":30,"value":444},"For example, software built for a small internal operations team may not support a high-volume self-service customer platform. A system built for one region may not support global compliance, localization, or multi-entity reporting. A product built around manual configuration may not support enterprise-scale automation.",{"type":25,"tag":26,"props":446,"children":447},{},[448],{"type":30,"value":449},"When the gap between the system’s design and the company’s strategy is too large, modernization may only delay the inevitable.",{"type":25,"tag":71,"props":451,"children":453},{"id":452},"_2-incremental-fixes-keep-failing",[454],{"type":30,"value":455},"2. Incremental Fixes Keep Failing",{"type":25,"tag":26,"props":457,"children":458},{},[459],{"type":30,"value":460},"CFOs should be especially alert to recurring “temporary” fixes.",{"type":25,"tag":26,"props":462,"children":463},{},[464],{"type":30,"value":465},"If the company has funded multiple rounds of patches, partial rewrites, upgrades, manual workarounds, and emergency stabilization efforts without improving the overall economics of the system, it may be time to stop financing the debt and invest in a new asset.",{"type":25,"tag":26,"props":467,"children":468},{},[469],{"type":30,"value":470},"A rebuild can be justified when incremental spending no longer produces durable value.",{"type":25,"tag":71,"props":472,"children":474},{"id":473},"_3-the-existing-codebase-is-too-fragile-to-change-safely",[475],{"type":30,"value":476},"3. The Existing Codebase Is Too Fragile to Change Safely",{"type":25,"tag":26,"props":478,"children":479},{},[480],{"type":30,"value":481},"If small changes regularly break unrelated features, estimates are unreliable, test coverage is weak, documentation is limited, and only a few people understand critical behavior, the system may be too risky to keep extending.",{"type":25,"tag":26,"props":483,"children":484},{},[485],{"type":30,"value":486},"That does not always mean the entire platform should be rebuilt.",{"type":25,"tag":26,"props":488,"children":489},{},[490],{"type":30,"value":491},"But if the company cannot safely modify a system it depends on, the business has limited control over a critical asset.",{"type":25,"tag":26,"props":493,"children":494},{},[495],{"type":30,"value":496},"That is a financial risk, not just a technical inconvenience.",{"type":25,"tag":71,"props":498,"children":500},{"id":499},"_4-the-technology-stack-is-a-dead-end",[501],{"type":30,"value":502},"4. The Technology Stack Is a Dead End",{"type":25,"tag":26,"props":504,"children":505},{},[506],{"type":30,"value":507},"Some systems are built on languages, frameworks, libraries, or platforms that are difficult to support. Vendor support may be ending. Security patches may be unavailable. Hiring talent may be expensive. Integration options may be limited.",{"type":25,"tag":26,"props":509,"children":510},{},[511],{"type":30,"value":512},"If the stack itself is constraining the business, modernization may require so much replacement that a rebuild becomes the clearer investment.",{"type":25,"tag":71,"props":514,"children":516},{"id":515},"_5-the-user-experience-needs-a-fundamental-redesign",[517],{"type":30,"value":518},"5. The User Experience Needs a Fundamental Redesign",{"type":25,"tag":26,"props":520,"children":521},{},[522],{"type":30,"value":523},"Sometimes the problem is not only the backend. The workflow itself may be wrong.",{"type":25,"tag":26,"props":525,"children":526},{},[527],{"type":30,"value":528},"If employees or customers rely on spreadsheets, duplicate data entry, manual approvals, offline processes, or support tickets because the software does not match how work actually happens, a rebuild may be necessary to redesign the experience around the business process.",{"type":25,"tag":26,"props":530,"children":531},{},[532],{"type":30,"value":533},"A modern interface placed on top of a flawed workflow may not deliver the operational improvement the company needs.",{"type":25,"tag":71,"props":535,"children":537},{"id":536},"when-modernization-is-the-better-investment",[538],{"type":30,"value":539},"When Modernization Is the Better Investment",{"type":25,"tag":26,"props":541,"children":542},{},[543],{"type":30,"value":544},"Modernization is often the more financially disciplined path, especially when the existing system still contains valuable business logic and supports critical operations.",{"type":25,"tag":26,"props":546,"children":547},{},[548],{"type":30,"value":549},"A modernization strategy can reduce risk by improving the system in phases instead of replacing it all at once.",{"type":25,"tag":71,"props":551,"children":553},{"id":552},"_1-the-core-business-logic-still-works",[554],{"type":30,"value":555},"1. The Core Business Logic Still Works",{"type":25,"tag":26,"props":557,"children":558},{},[559],{"type":30,"value":560},"Many legacy systems look outdated but contain years of valuable domain knowledge.",{"type":25,"tag":26,"props":562,"children":563},{},[564],{"type":30,"value":565},"Pricing rules, approval workflows, operational edge cases, compliance logic, reporting calculations, and customer-specific requirements may all be embedded in the software.",{"type":25,"tag":26,"props":567,"children":568},{},[569],{"type":30,"value":570},"Throwing that away can be expensive and risky.",{"type":25,"tag":26,"props":572,"children":573},{},[574,576,581],{"type":30,"value":575},"Modernization allows the company to preserve what works while improving the technical foundation around it. As Art+Logic has put it, the goal is not to preserve every technical decision; it is to preserve the value those decisions created. (",{"type":25,"tag":158,"props":577,"children":579},{"href":160,"rel":578},[162],[580],{"type":30,"value":165},{"type":30,"value":167},{"type":25,"tag":71,"props":583,"children":585},{"id":584},"_2-the-business-cannot-tolerate-big-bang-disruption",[586],{"type":30,"value":587},"2. The Business Cannot Tolerate Big-Bang Disruption",{"type":25,"tag":26,"props":589,"children":590},{},[591],{"type":30,"value":592},"A full replacement can introduce operational risk, especially if the system supports revenue, fulfillment, logistics, billing, customer service, or compliance.",{"type":25,"tag":26,"props":594,"children":595},{},[596],{"type":30,"value":597},"Modernization can be phased around business priorities. The team can improve performance, security, integrations, reporting, and user experience while the existing system continues to operate.",{"type":25,"tag":26,"props":599,"children":600},{},[601],{"type":30,"value":602},"For finance leaders, this matters because phased modernization can make spend more predictable and outcomes easier to validate.",{"type":25,"tag":71,"props":604,"children":606},{"id":605},"_3-the-main-problems-are-isolated",[607],{"type":30,"value":608},"3. The Main Problems Are Isolated",{"type":25,"tag":26,"props":610,"children":611},{},[612],{"type":30,"value":613},"Not every legacy system is broken everywhere.",{"type":25,"tag":26,"props":615,"children":616},{},[617],{"type":30,"value":618},"The application may have a slow reporting module, an unreliable integration layer, an outdated interface, a manual deployment process, or a scaling bottleneck. If the pain is concentrated in specific areas, a targeted modernization effort may produce better ROI than a full rebuild.",{"type":25,"tag":26,"props":620,"children":621},{},[622,624,629],{"type":30,"value":623},"This is where “start with the pain, not the platform” becomes an important principle. Moving to the cloud or rewriting in a new framework is not inherently valuable. Solving the friction that is slowing development, operations, reporting, or customer experience is. (",{"type":25,"tag":158,"props":625,"children":627},{"href":234,"rel":626},[162],[628],{"type":30,"value":165},{"type":30,"value":167},{"type":25,"tag":71,"props":631,"children":633},{"id":632},"_4-the-company-needs-value-sooner",[634],{"type":30,"value":635},"4. The Company Needs Value Sooner",{"type":25,"tag":26,"props":637,"children":638},{},[639],{"type":30,"value":640},"Rebuilds often require a long investment period before the business sees a meaningful return.",{"type":25,"tag":26,"props":642,"children":643},{},[644],{"type":30,"value":645},"Modernization can produce near-term wins: faster workflows, improved reporting, reduced support burden, better performance, stronger security, easier deployments, or lower infrastructure costs.",{"type":25,"tag":26,"props":647,"children":648},{},[649],{"type":30,"value":650},"That matters when budgets are tight, when the business needs evidence before approving a larger transformation, or when leadership wants to reduce risk through measurable checkpoints.",{"type":25,"tag":71,"props":652,"children":654},{"id":653},"_5-the-existing-system-can-be-gradually-untangled",[655],{"type":30,"value":656},"5. The Existing System Can Be Gradually Untangled",{"type":25,"tag":26,"props":658,"children":659},{},[660],{"type":30,"value":661},"Some legacy systems can be improved through a phased approach: isolate high-friction modules, build modern replacements alongside the current system, shift workloads gradually, and retire old components as the replacement proves itself.",{"type":25,"tag":26,"props":663,"children":664},{},[665,667,672],{"type":30,"value":666},"Art+Logic has described this as decoupling rather than demolishing. Many legacy systems can be modernized one piece at a time, especially when the team creates parallel paths that let the current system keep running while modern capabilities gradually take over. (",{"type":25,"tag":158,"props":668,"children":670},{"href":234,"rel":669},[162],[671],{"type":30,"value":165},{"type":30,"value":167},{"type":25,"tag":26,"props":674,"children":675},{},[676],{"type":30,"value":677},"This can combine the strategic benefits of replacement with the financial control of staged investment.",{"type":25,"tag":71,"props":679,"children":681},{"id":680},"the-cfos-evaluation-framework",[682],{"type":30,"value":683},"The CFO’s Evaluation Framework",{"type":25,"tag":26,"props":685,"children":686},{},[687],{"type":30,"value":688},"The rebuild-versus-modernize decision should be made through business, financial, and technical analysis.",{"type":25,"tag":26,"props":690,"children":691},{},[692],{"type":30,"value":693},"Here are the questions CFOs should ask before approving either path.",{"type":25,"tag":71,"props":695,"children":697},{"id":696},"_1-what-business-outcome-are-we-buying",[698],{"type":30,"value":699},"1. What Business Outcome Are We Buying?",{"type":25,"tag":26,"props":701,"children":702},{},[703],{"type":30,"value":704},"Do not begin with the architecture; instead, begin with the business result.",{"type":25,"tag":26,"props":706,"children":707},{},[708],{"type":30,"value":709},"Are you trying to reduce operating costs? Increase engineering velocity? Improve customer retention? Launch a new product line? Reduce cybersecurity risk? Improve reporting and forecasting? Support more transaction volume? Eliminate manual work? Improve compliance? Prepare for acquisition, investment, or audit?",{"type":25,"tag":26,"props":711,"children":712},{},[713],{"type":30,"value":714},"A rebuild or modernization effort should be tied to specific outcomes. Without that clarity, the project can become a broad technical improvement program with unclear ROI.",{"type":25,"tag":26,"props":716,"children":717},{},[718],{"type":30,"value":719},"A useful test is whether the investment can be explained in business language:",{"type":25,"tag":26,"props":721,"children":722},{},[723],{"type":30,"value":724},"“We are modernizing this platform so we can reduce manual order processing.”",{"type":25,"tag":26,"props":726,"children":727},{},[728],{"type":30,"value":729},"“We are replacing this architecture because it cannot support the transaction volume required for our growth plan.”",{"type":25,"tag":26,"props":731,"children":732},{},[733],{"type":30,"value":734},"“We are improving deployment and testing so product teams can release safely and more often.”",{"type":25,"tag":26,"props":736,"children":737},{},[738],{"type":30,"value":739},"The more specific the outcome, the easier it is to evaluate the right path.",{"type":25,"tag":71,"props":741,"children":743},{"id":742},"_2-what-is-the-true-cost-of-the-current-system",[744],{"type":30,"value":745},"2. What Is the True Cost of the Current System?",{"type":25,"tag":26,"props":747,"children":748},{},[749],{"type":30,"value":750},"CFOs should look beyond hosting bills and engineering headcount.",{"type":25,"tag":26,"props":752,"children":753},{},[754],{"type":30,"value":755},"The total cost of ownership may include maintenance labor, incident response, downtime, manual operations, customer support volume, delayed revenue initiatives, compliance gaps, security remediation, vendor fees, data reconciliation, reporting inefficiencies, onboarding time, and recruiting challenges.",{"type":25,"tag":26,"props":757,"children":758},{},[759],{"type":30,"value":760},"A legacy platform may appear inexpensive because many costs are scattered across departments.",{"type":25,"tag":26,"props":762,"children":763},{},[764],{"type":30,"value":765},"Pulling those costs together often changes the investment conversation.",{"type":25,"tag":71,"props":767,"children":769},{"id":768},"_3-what-risks-are-we-carrying-today",[770],{"type":30,"value":771},"3. What Risks Are We Carrying Today?",{"type":25,"tag":26,"props":773,"children":774},{},[775],{"type":30,"value":776},"Modernization and rebuild projects carry delivery risk.",{"type":25,"tag":26,"props":778,"children":779},{},[780],{"type":30,"value":781},"But doing nothing also carries risk.",{"type":25,"tag":26,"props":783,"children":784},{},[785],{"type":30,"value":786},"CFOs should ask:",{"type":25,"tag":788,"props":789,"children":790},"ul",{},[791,797,802,807,812,817,822],{"type":25,"tag":792,"props":793,"children":794},"li",{},[795],{"type":30,"value":796},"What happens if a key developer leaves?",{"type":25,"tag":792,"props":798,"children":799},{},[800],{"type":30,"value":801},"What happens if transaction volume doubles?",{"type":25,"tag":792,"props":803,"children":804},{},[805],{"type":30,"value":806},"What happens if a vendor discontinues support?",{"type":25,"tag":792,"props":808,"children":809},{},[810],{"type":30,"value":811},"What happens if a major customer requests an integration we cannot support?",{"type":25,"tag":792,"props":813,"children":814},{},[815],{"type":30,"value":816},"What happens if we need to pass a stricter security review?",{"type":25,"tag":792,"props":818,"children":819},{},[820],{"type":30,"value":821},"What happens if the system goes down during a peak period?",{"type":25,"tag":792,"props":823,"children":824},{},[825],{"type":30,"value":826},"What happens if reporting remains unreliable?",{"type":25,"tag":26,"props":828,"children":829},{},[830],{"type":30,"value":831},"The decision should compare the risk of change against the risk of inaction.",{"type":25,"tag":71,"props":833,"children":835},{"id":834},"_4-can-we-fund-this-in-stages",[836],{"type":30,"value":837},"4. Can We Fund This in Stages?",{"type":25,"tag":26,"props":839,"children":840},{},[841],{"type":30,"value":842},"Large software projects become more manageable when they are broken into funded phases with measurable checkpoints.",{"type":25,"tag":26,"props":844,"children":845},{},[846],{"type":30,"value":847},"Rather than approving an open-ended rebuild, CFOs can ask for a staged plan:",{"type":25,"tag":849,"props":850,"children":851},"ol",{},[852,857,862,867,872],{"type":25,"tag":792,"props":853,"children":854},{},[855],{"type":30,"value":856},"Assessment and discovery",{"type":25,"tag":792,"props":858,"children":859},{},[860],{"type":30,"value":861},"Architecture and roadmap",{"type":25,"tag":792,"props":863,"children":864},{},[865],{"type":30,"value":866},"Highest-risk component replacement",{"type":25,"tag":792,"props":868,"children":869},{},[870],{"type":30,"value":871},"First measurable business outcome",{"type":25,"tag":792,"props":873,"children":874},{},[875],{"type":30,"value":876},"Expansion based on validated results",{"type":25,"tag":26,"props":878,"children":879},{},[880],{"type":30,"value":881},"This structure helps avoid the common trap of committing to a large technical vision before the business has evidence that the approach works.",{"type":25,"tag":26,"props":883,"children":884},{},[885],{"type":30,"value":886},"It also creates opportunities to stop, adjust, or accelerate based on results.",{"type":25,"tag":71,"props":888,"children":890},{"id":889},"_5-what-should-we-not-rebuild",[891],{"type":30,"value":892},"5. What Should We Not Rebuild?",{"type":25,"tag":26,"props":894,"children":895},{},[896],{"type":30,"value":897},"One of the biggest mistakes in software replacement projects is assuming the new system must recreate every feature in the old system.",{"type":25,"tag":26,"props":899,"children":900},{},[901],{"type":30,"value":902},"Legacy software often contains features that are unused, redundant, confusing, or tied to outdated processes. Rebuilding everything can waste budget and preserve complexity.",{"type":25,"tag":26,"props":904,"children":905},{},[906],{"type":30,"value":907},"Before approving a rebuild, CFOs should insist on a serious feature and workflow review.",{"type":25,"tag":26,"props":909,"children":910},{},[911],{"type":30,"value":912},"The goal is not to copy the old system.",{"type":25,"tag":26,"props":914,"children":915},{},[916],{"type":30,"value":917},"The goal is to build the system the business actually needs now.",{"type":25,"tag":71,"props":919,"children":921},{"id":920},"_6-how-will-we-measure-roi",[922],{"type":30,"value":923},"6. How Will We Measure ROI?",{"type":25,"tag":26,"props":925,"children":926},{},[927],{"type":30,"value":928},"Software ROI is not always immediate, but it should be measurable.",{"type":25,"tag":26,"props":930,"children":931},{},[932],{"type":30,"value":933},"Potential metrics include lower maintenance spend, reduced manual labor, faster release cycles, fewer incidents, lower support volume, faster onboarding, improved conversion, higher retention, increased transaction capacity, reduced infrastructure cost, better reporting accuracy, shorter cycle times, improved customer satisfaction, and reduced compliance exposure.",{"type":25,"tag":26,"props":935,"children":936},{},[937],{"type":30,"value":938},"The right metrics depend on the system.",{"type":25,"tag":26,"props":940,"children":941},{},[942],{"type":30,"value":943},"An internal operations platform may justify investment through labor savings and process efficiency. A customer-facing product may justify investment through retention, expansion revenue, and faster feature delivery.",{"type":25,"tag":26,"props":945,"children":946},{},[947],{"type":30,"value":948},"The important point is to define success before the work begins.",{"type":25,"tag":71,"props":950,"children":952},{"id":951},"the-common-failure-mode-rebuilding-without-reducing-complexity",[953],{"type":30,"value":954},"The Common Failure Mode: Rebuilding Without Reducing Complexity",{"type":25,"tag":26,"props":956,"children":957},{},[958],{"type":30,"value":959},"A software rebuild can fail even when the new technology is better.",{"type":25,"tag":26,"props":961,"children":962},{},[963],{"type":30,"value":964},"That usually happens when the project recreates old complexity instead of solving it.",{"type":25,"tag":26,"props":966,"children":967},{},[968],{"type":30,"value":969},"The team copies every screen, every field, every exception, every report, every workflow, and every edge case into a new system. The result is a more expensive version of the same problem.",{"type":25,"tag":26,"props":971,"children":972},{},[973],{"type":30,"value":974},"For CFOs, this is a governance issue.",{"type":25,"tag":26,"props":976,"children":977},{},[978],{"type":30,"value":979},"A rebuild should not be treated as a technical translation exercise. It should be treated as a business redesign opportunity.",{"type":25,"tag":26,"props":981,"children":982},{},[983],{"type":30,"value":984},"Which workflows can be simplified? Which approvals can be automated? Which reports are no longer useful? Which integrations can be standardized? Which customer exceptions are actually margin-eroding customizations?",{"type":25,"tag":26,"props":986,"children":987},{},[988],{"type":30,"value":989},"The value of a rebuild comes from improving how the business operates, not just changing the code.",{"type":25,"tag":71,"props":991,"children":993},{"id":992},"the-other-failure-mode-modernizing-without-a-strategy",[994],{"type":30,"value":995},"The Other Failure Mode: Modernizing Without a Strategy",{"type":25,"tag":26,"props":997,"children":998},{},[999],{"type":30,"value":1000},"Modernization can also fail when it becomes a series of disconnected technical upgrades.",{"type":25,"tag":26,"props":1002,"children":1003},{},[1004],{"type":30,"value":1005},"A team updates a framework, moves hosting environments, rewrites a few services, improves deployment pipelines, and cleans up code. Each activity may be reasonable, but the business impact is unclear.",{"type":25,"tag":26,"props":1007,"children":1008},{},[1009],{"type":30,"value":1010},"The result is modernization activity without financial momentum.",{"type":25,"tag":26,"props":1012,"children":1013},{},[1014],{"type":30,"value":1015},"A strong modernization roadmap should connect technical work to business outcomes.",{"type":25,"tag":26,"props":1017,"children":1018},{},[1019],{"type":30,"value":1020},"API work should support integrations, partnerships, automation, or customer self-service. Cloud migration should support scalability, resilience, cost visibility, or deployment speed. Refactoring should reduce change failure rates, maintenance cost, or release bottlenecks. Data modernization should improve reporting, forecasting, compliance, or operational decision-making. UX improvements should reduce training time, support volume, or task completion time.",{"type":25,"tag":26,"props":1022,"children":1023},{},[1024],{"type":30,"value":1025},"Modernization is most valuable when every technical improvement has a business reason behind it.",{"type":25,"tag":71,"props":1027,"children":1029},{"id":1028},"a-practical-decision-matrix-for-cfos",[1030],{"type":30,"value":1031},"A Practical Decision Matrix for CFOs",{"type":25,"tag":26,"props":1033,"children":1034},{},[1035],{"type":30,"value":1036},"Consider rebuilding when:",{"type":25,"tag":788,"props":1038,"children":1039},{},[1040,1045,1050,1055,1060,1065,1070],{"type":25,"tag":792,"props":1041,"children":1042},{},[1043],{"type":30,"value":1044},"The current system cannot support the future business model.",{"type":25,"tag":792,"props":1046,"children":1047},{},[1048],{"type":30,"value":1049},"The architecture is fundamentally misaligned with strategic goals.",{"type":25,"tag":792,"props":1051,"children":1052},{},[1053],{"type":30,"value":1054},"The codebase is too fragile or poorly understood to change safely.",{"type":25,"tag":792,"props":1056,"children":1057},{},[1058],{"type":30,"value":1059},"The technology stack is obsolete or difficult to staff.",{"type":25,"tag":792,"props":1061,"children":1062},{},[1063],{"type":30,"value":1064},"The user experience requires a fundamental workflow redesign.",{"type":25,"tag":792,"props":1066,"children":1067},{},[1068],{"type":30,"value":1069},"Incremental fixes have repeatedly failed to improve the economics.",{"type":25,"tag":792,"props":1071,"children":1072},{},[1073],{"type":30,"value":1074},"The cost of preserving the old system is higher than that of replacing it.",{"type":25,"tag":26,"props":1076,"children":1077},{},[1078],{"type":30,"value":1079},"Consider modernizing when:",{"type":25,"tag":788,"props":1081,"children":1082},{},[1083,1088,1093,1098,1103,1108,1113],{"type":25,"tag":792,"props":1084,"children":1085},{},[1086],{"type":30,"value":1087},"The system still contains valuable business logic.",{"type":25,"tag":792,"props":1089,"children":1090},{},[1091],{"type":30,"value":1092},"The main problems are specific and addressable.",{"type":25,"tag":792,"props":1094,"children":1095},{},[1096],{"type":30,"value":1097},"The business needs continuity during improvement.",{"type":25,"tag":792,"props":1099,"children":1100},{},[1101],{"type":30,"value":1102},"You need to reduce risk through phased delivery.",{"type":25,"tag":792,"props":1104,"children":1105},{},[1106],{"type":30,"value":1107},"The platform can be gradually refactored or decomposed.",{"type":25,"tag":792,"props":1109,"children":1110},{},[1111],{"type":30,"value":1112},"Near-term ROI matters.",{"type":25,"tag":792,"props":1114,"children":1115},{},[1116],{"type":30,"value":1117},"The organization is not ready for full replacement.",{"type":25,"tag":26,"props":1119,"children":1120},{},[1121],{"type":30,"value":1122},"Consider a hybrid approach when:",{"type":25,"tag":788,"props":1124,"children":1125},{},[1126,1131,1136,1141,1146],{"type":25,"tag":792,"props":1127,"children":1128},{},[1129],{"type":30,"value":1130},"Some components are salvageable, and others are not.",{"type":25,"tag":792,"props":1132,"children":1133},{},[1134],{"type":30,"value":1135},"The business needs both continuity and strategic change.",{"type":25,"tag":792,"props":1137,"children":1138},{},[1139],{"type":30,"value":1140},"You can replace high-risk areas first while preserving stable functions.",{"type":25,"tag":792,"props":1142,"children":1143},{},[1144],{"type":30,"value":1145},"A phased roadmap can deliver measurable value before full replacement.",{"type":25,"tag":792,"props":1147,"children":1148},{},[1149],{"type":30,"value":1150},"The system is too important for a big-bang cutover.",{"type":25,"tag":26,"props":1152,"children":1153},{},[1154],{"type":30,"value":1155},"In many cases, the hybrid path is the most financially responsible option.",{"type":25,"tag":71,"props":1157,"children":1159},{"id":1158},"why-an-independent-technical-assessment-helps",[1160],{"type":30,"value":1161},"Why an Independent Technical Assessment Helps",{"type":25,"tag":26,"props":1163,"children":1164},{},[1165],{"type":30,"value":1166},"Finance leaders do not need to become software architects.",{"type":25,"tag":26,"props":1168,"children":1169},{},[1170],{"type":30,"value":1171},"But they do need enough objective information to make a sound investment decision.",{"type":25,"tag":26,"props":1173,"children":1174},{},[1175],{"type":30,"value":1176},"An independent technical assessment can help answer:",{"type":25,"tag":788,"props":1178,"children":1179},{},[1180,1185,1190,1195,1200,1205,1210,1215],{"type":25,"tag":792,"props":1181,"children":1182},{},[1183],{"type":30,"value":1184},"What is the current state of the system?",{"type":25,"tag":792,"props":1186,"children":1187},{},[1188],{"type":30,"value":1189},"Where are the highest costs and risks?",{"type":25,"tag":792,"props":1191,"children":1192},{},[1193],{"type":30,"value":1194},"Which parts are worth preserving?",{"type":25,"tag":792,"props":1196,"children":1197},{},[1198],{"type":30,"value":1199},"Which parts should be replaced?",{"type":25,"tag":792,"props":1201,"children":1202},{},[1203],{"type":30,"value":1204},"What are the realistic options?",{"type":25,"tag":792,"props":1206,"children":1207},{},[1208],{"type":30,"value":1209},"What are the tradeoffs in cost, timeline, risk, and business impact?",{"type":25,"tag":792,"props":1211,"children":1212},{},[1213],{"type":30,"value":1214},"What should be done first?",{"type":25,"tag":792,"props":1216,"children":1217},{},[1218],{"type":30,"value":1219},"What outcomes can be measured?",{"type":25,"tag":26,"props":1221,"children":1222},{},[1223],{"type":30,"value":1224},"This step is especially valuable when internal stakeholders disagree.",{"type":25,"tag":26,"props":1226,"children":1227},{},[1228],{"type":30,"value":1229},"Engineers may see the pain of the current system every day. Business teams may fear disruption. Executives may want speed. Finance may need predictability. An assessment creates a shared fact base for the decision.",{"type":25,"tag":71,"props":1231,"children":1233},{"id":1232},"the-best-answer-is-often-sequenced-not-binary",[1234],{"type":30,"value":1235},"The Best Answer Is Often Sequenced, Not Binary",{"type":25,"tag":26,"props":1237,"children":1238},{},[1239],{"type":30,"value":1240},"The rebuild-versus-modernize debate is often framed as an either/or decision.",{"type":25,"tag":26,"props":1242,"children":1243},{},[1244],{"type":30,"value":1245},"In reality, the best strategy may be sequenced.",{"type":25,"tag":26,"props":1247,"children":1248},{},[1249],{"type":30,"value":1250},"Start by understanding what the current system actually does. Identify the highest-cost and highest-risk areas. Stabilize what needs to keep running. Improve visibility, security, deployment processes, and test coverage. Replace high-friction workflows one at a time. Build new capabilities around the legacy core. Migrate users gradually. Retire old components when the replacement has proven itself.",{"type":25,"tag":26,"props":1252,"children":1253},{},[1254],{"type":30,"value":1255},"This kind of phased approach gives CFOs more control.",{"type":25,"tag":26,"props":1257,"children":1258},{},[1259],{"type":30,"value":1260},"It reduces the risk of a large sunk-cost project. It creates measurable checkpoints. It allows the business to learn as it invests. And it can deliver value before the entire transformation is complete.",{"type":25,"tag":26,"props":1262,"children":1263},{},[1264,1266,1271],{"type":30,"value":1265},"Modernization is not about replacing the past for its own sake. It is about creating a foundation that can support the future. (",{"type":25,"tag":158,"props":1267,"children":1269},{"href":160,"rel":1268},[162],[1270],{"type":30,"value":165},{"type":30,"value":167},{"type":25,"tag":71,"props":1273,"children":1275},{"id":1274},"final-takeaway-dont-pay-twice-for-the-same-complexity",[1276],{"type":30,"value":1277},"Final Takeaway: Don’t Pay Twice for the Same Complexity",{"type":25,"tag":26,"props":1279,"children":1280},{},[1281],{"type":30,"value":1282},"Rebuilding and modernizing software can both be smart investments.",{"type":25,"tag":26,"props":1284,"children":1285},{},[1286],{"type":30,"value":1287},"They can also both waste money if the business case is vague.",{"type":25,"tag":26,"props":1289,"children":1290},{},[1291],{"type":30,"value":1292},"A rebuild is justified when the current system cannot support where the company is going. Modernization is often better when the existing system still has value and the business needs a lower-risk path to improvement. A hybrid approach may offer the best balance: preserve what works, replace what limits growth, and fund the work in stages.",{"type":25,"tag":26,"props":1294,"children":1295},{},[1296],{"type":30,"value":1297},"For CFOs, the decision should come down to this:",{"type":25,"tag":26,"props":1299,"children":1300},{},[1301],{"type":25,"tag":45,"props":1302,"children":1303},{},[1304],{"type":30,"value":1305},"Which path gives the company the strongest future capability for the lowest acceptable risk?",{"type":25,"tag":26,"props":1307,"children":1308},{},[1309],{"type":30,"value":1310},"The answer requires technical insight, but it should be evaluated through financial discipline.",{"type":25,"tag":26,"props":1312,"children":1313},{},[1314],{"type":30,"value":1315},"The goal is not to own newer software.",{"type":25,"tag":26,"props":1317,"children":1318},{},[1319],{"type":30,"value":1320},"The goal is to invest in a platform that helps the business move faster, operate with less friction, reduce risk, and create durable value.",{"type":25,"tag":1322,"props":1323,"children":1324},"hr",{},[],{"type":25,"tag":71,"props":1326,"children":1328},{"id":1327},"faqs",[1329],{"type":30,"value":1330},"FAQs",{"type":25,"tag":245,"props":1332,"children":1334},{"id":1333},"what-is-the-difference-between-rebuilding-and-modernizing-software",[1335],{"type":30,"value":1336},"What is the difference between rebuilding and modernizing software?",{"type":25,"tag":26,"props":1338,"children":1339},{},[1340],{"type":30,"value":1341},"Rebuilding software means replacing an existing system with a new one, usually built from the ground up. Modernizing software means improving the existing system through targeted updates such as refactoring, cloud migration, security improvements, new integrations, observability, or user experience enhancements.",{"type":25,"tag":245,"props":1343,"children":1345},{"id":1344},"is-it-cheaper-to-modernize-software-than-to-rebuild-it",[1346],{"type":30,"value":1347},"Is it cheaper to modernize software than to rebuild it?",{"type":25,"tag":26,"props":1349,"children":1350},{},[1351],{"type":30,"value":1352},"Modernization is often less expensive upfront because it can be done in phases and may preserve valuable parts of the existing system. However, if the current architecture is fundamentally flawed or no longer supports the business model, repeated modernization efforts can become more expensive than rebuilding.",{"type":25,"tag":245,"props":1354,"children":1356},{"id":1355},"when-should-a-company-rebuild-legacy-software",[1357],{"type":30,"value":1358},"When should a company rebuild legacy software?",{"type":25,"tag":26,"props":1360,"children":1361},{},[1362],{"type":30,"value":1363},"A rebuild may make sense when the existing system cannot support future growth, relies on obsolete technology, creates significant operational risk, or requires so many fixes that replacement becomes the more financially responsible option.",{"type":25,"tag":245,"props":1365,"children":1367},{"id":1366},"when-is-software-modernization-the-better-choice",[1368],{"type":30,"value":1369},"When is software modernization the better choice?",{"type":25,"tag":26,"props":1371,"children":1372},{},[1373],{"type":30,"value":1374},"Modernization is usually better when the core system still works, contains valuable business logic, and can be improved incrementally. It is also a good option when the business needs continuity and wants to reduce delivery risk through phased investment.",{"type":25,"tag":245,"props":1376,"children":1378},{"id":1377},"what-should-cfos-evaluate-before-approving-a-software-rebuild",[1379],{"type":30,"value":1380},"What should CFOs evaluate before approving a software rebuild?",{"type":25,"tag":26,"props":1382,"children":1383},{},[1384],{"type":30,"value":1385},"CFOs should evaluate the total cost of ownership, current system risks, business outcomes, delivery timeline, data migration complexity, change management needs, and measurable ROI. They should also ask whether the project is simplifying business complexity or simply recreating it in a new system.",{"type":25,"tag":245,"props":1387,"children":1389},{"id":1388},"can-a-company-rebuild-and-modernize-at-the-same-time",[1390],{"type":30,"value":1391},"Can a company rebuild and modernize at the same time?",{"type":25,"tag":26,"props":1393,"children":1394},{},[1395],{"type":30,"value":1396},"Yes. Many successful projects use a hybrid strategy. The company may modernize stable parts of the system while rebuilding high-risk or high-value components. This can reduce disruption while still moving the business toward a better long-term architecture.",{"type":25,"tag":26,"props":1398,"children":1399},{},[1400],{"type":30,"value":1401},"This version now has a clearer connection to the earlier Art+Logic newsletter content while still standing on its own as a CFO-focused blog post.",{"title":8,"searchDepth":1403,"depth":1403,"links":1404},3,[1405,1406,1407,1414,1415,1416,1417,1418,1419,1420,1421,1422,1423,1424,1425,1426,1427,1428,1429,1430,1431,1432,1433,1434,1435,1436,1437,1438,1439,1440],{"id":73,"depth":1403,"text":76},{"id":138,"depth":1403,"text":141},{"id":201,"depth":1403,"text":204,"children":1408},[1409,1411,1412,1413],{"id":247,"depth":1410,"text":250},4,{"id":268,"depth":1410,"text":271},{"id":299,"depth":1410,"text":302},{"id":326,"depth":1410,"text":329},{"id":347,"depth":1403,"text":350},{"id":410,"depth":1403,"text":413},{"id":426,"depth":1403,"text":429},{"id":452,"depth":1403,"text":455},{"id":473,"depth":1403,"text":476},{"id":499,"depth":1403,"text":502},{"id":515,"depth":1403,"text":518},{"id":536,"depth":1403,"text":539},{"id":552,"depth":1403,"text":555},{"id":584,"depth":1403,"text":587},{"id":605,"depth":1403,"text":608},{"id":632,"depth":1403,"text":635},{"id":653,"depth":1403,"text":656},{"id":680,"depth":1403,"text":683},{"id":696,"depth":1403,"text":699},{"id":742,"depth":1403,"text":745},{"id":768,"depth":1403,"text":771},{"id":834,"depth":1403,"text":837},{"id":889,"depth":1403,"text":892},{"id":920,"depth":1403,"text":923},{"id":951,"depth":1403,"text":954},{"id":992,"depth":1403,"text":995},{"id":1028,"depth":1403,"text":1031},{"id":1158,"depth":1403,"text":1161},{"id":1232,"depth":1403,"text":1235},{"id":1274,"depth":1403,"text":1277},{"id":1327,"depth":1403,"text":1330,"children":1441},[1442,1443,1444,1445,1446,1447],{"id":1333,"depth":1410,"text":1336},{"id":1344,"depth":1410,"text":1347},{"id":1355,"depth":1410,"text":1358},{"id":1366,"depth":1410,"text":1369},{"id":1377,"depth":1410,"text":1380},{"id":1388,"depth":1410,"text":1391},"markdown","content:cperez:2026-07-16:rebuild-vs-modernize-software-cfo-guide.md","content","cperez/2026-07-16/rebuild-vs-modernize-software-cfo-guide.md","cperez/2026-07-16/rebuild-vs-modernize-software-cfo-guide","md",[1455,1468,1477,1490,1505,1517,1525,1535,1546,1555,1567,1578,1589,1598,1608,1619,1632,1643,1652,1662,1670,1677,1686,1694,1703,1713,1723,1732,1741,1749,1760,1768,1776,1785,1793,1803,1811,1819,1827,1835,1843,1851,1859,1869,1877,1887,1895,1905,1915,1926,1936,1946,1960,1970,1983,1992,2003,2014,2017,2030,2042,2053,2063,2076,2085,2095,2105,2115,2127,2139,2153,2167,2182,2190,2198,2207,2216,2225,2234,2243,2252,2261,2270,2279,2290,2303,2313,2321,2329,2337,2345,2357,2369,2379,2388,2397,2407,2416,2426,2435],{"_path":1456,"title":1457,"description":1458,"image":1459,"publishDate":1460,"tags":1461,"_id":1464,"author":1465},"/alalande/2023-1/escaping_text","Thinking Like a Programmer: Escaping Text","In this progressive and vivid explanation, we explore the HOW and WHY of quoting, nesting, and escaping text.","/alalande/2023-1/img/header.png","2024-02-15",[1462,1463],"series","educational","content:alalande:2023-1:escaping_text.md",{"user":1466,"name":1467},"alalande","Anthony Lalande",{"_path":1469,"title":1470,"description":1471,"image":1472,"publishDate":1473,"tags":1474,"_id":1475,"author":1476},"/alalande/2023-2/heuristics","Thinking Like a Programmer: Heuristics","We want to help you turbo-charge your decision making.","/alalande/2023-2/img/heuristics.png","2024-03-15",[1462,1463],"content:alalande:2023-2:heuristics.md",{"user":1466,"name":1467},{"_path":1478,"title":1479,"description":1480,"tags":1481,"publishDate":1484,"image":1485,"_id":1486,"author":1487},"/areichert/2023-10/rapid-testing-techniques-for-web-and-mobile","Rapid Testing Techniques for Web & Mobile Apps","Testing rapidly or the need to test quickly under shortened execution cycles is not new. Rapid testing has been around for as long as software testing has existed but increases when a product release is imminent, strained, or behind schedule. There are many reasons development gets behind schedule. Similar to testing, development is prone to surprise requirements changes and increases in scope and complexity.",[1482,1483],"software-testing","qa","2024-06-01","/areichert/2023-10/img/rapid_testing.png","content:areichert:2023-10:Rapid Testing techniques for web and mobile.md",{"user":1488,"name":1489},"areichert","Amy Reichert",{"_path":1491,"title":1492,"description":1493,"image":1494,"publishDate":1495,"tags":1496,"_id":1501,"author":1502},"/asherbrooke/2020-4/watchwah","Bringing an Idea to Life: WatchWah Proof of Concept","\"Wouldn't it be cool if...\"","/asherbrooke/2020-4/img/Guitar_and_Watch.jpeg","2020-04-01",[1497,1498,1499,1500],"ios","apple","watch","juce","content:asherbrooke:2020-4:watchwah.md",{"user":1503,"name":1504},"asherbrooke","Andrew Sherbrooke",{"_path":1506,"title":1507,"description":1508,"publishDate":1509,"tags":1510,"_id":1513,"author":1514},"/avogan/2012-07/salt","What Your Users Don't Know (Part 1)","What's wrong with this code?","2012-07-13",[1511,1512,1462],"cryptography","security","content:avogan:2012-07:salt.md",{"user":1515,"name":1516},"avogan","Andrew Vogan",{"_path":1518,"title":1519,"description":1520,"publishDate":1521,"tags":1522,"_id":1523,"author":1524},"/avogan/2012-07/salt-2","What Your Users Don't Know (Part 2)","In my last post we saw that what your users don't know can hurt them. In other words, how securely you handle your users' private data behind the scenes can have profound implications both for your business and your users' well being. To put it bluntly, it's bad for your business to be publicly shamed over your handling of sensitive data, and it's bad for your users to have their bank accounts pilfered -- those being some of the worse case scenarios.","2012-07-26",[1511,1512,1462],"content:avogan:2012-07:salt-2.md",{"user":1515,"name":1516},{"_path":1526,"title":1527,"description":1528,"publishDate":1529,"image":1530,"_id":1531,"author":1532},"/bporter/2012-5/cd_player","My First CD Player","I started college right about the time when the first CD players were coming onto the market -- there weren't many available, and they were all obscenely expensive. At the time, my dad was dong a lot of traveling to Japan for business, and he was able to bring me a really nice Yamaha CD player back from a shop in Akihabara for about 1/4th of what a similar unit would have cost me here in the US.","2012-05-01","/bporter/2012-5/img/cd_player.jpg","content:bporter:2012-5:cd_player.md",{"user":1533,"name":1534},"bporter","Brett Porter",{"_path":1536,"title":1537,"description":1538,"publishDate":1539,"tags":1540,"image":1543,"_id":1544,"author":1545},"/bporter/2012-5/improtech","ImproTech Paris-New York 2012","Last week, I took a vacation day to attend one day of workshops at NYU as part of ImproTech 2012 Paris-New York That website descibes the event as:","2012-05-24",[1541,1542],"improvisation","music","/bporter/2012-5/img/affichemartin.jpg","content:bporter:2012-5:improtech.md",{"user":1533,"name":1534},{"_path":1547,"title":1548,"description":1549,"publishDate":1550,"tags":1551,"_id":1553,"author":1554},"/bporter/2012-5/learntocode","Yes, Do Learn To Code!","My usual pre-work routine is to walk the dog (working at home, this is my counterpart to a commute), pour my first cup of coffee, and then curl up for a little while with Google Reader. I don't know if it's because I've selected feeds that are too closely aligned with my values and personal agenda, but it's really rare that I'll read a post that is just so wrong that it makes me angry. Jeff Atwood wrote a post like that: Please Don't Learn To Code","2012-05-15",[1552],"learn-to-code","content:bporter:2012-5:learntocode.md",{"user":1533,"name":1534},{"_path":1556,"title":1557,"description":1558,"publishDate":1559,"tags":1560,"image":1564,"_id":1565,"author":1566},"/bporter/2012-6/dsl","Watch Your Language","Interesting to see a theme emerge in my Pinboard account this week -- lots of stuff about the idea of 'programming language'. I've spent the last few weeks preparing to dive back into a personal interactive music project that I've been working on sporadically since I was in graduate school. I had recently realized that the conceptual roadblock I hit before my last hiatus was something that I'd need to address by adding some sort of little programming language into the system. After following Martin Fowler's many blog posts over the years discussing domain specific languages, I finally broke down and bought his book on the topic. It's too early yet for me to have much concrete to say about the book, but I remember getting enough out of those blog posts to be confident that it will be worth the money and time to read.","2012-06-29",[1561,1562,1563],"dsl","erlang","go","/bporter/2012-6/img/dsl.jpg","content:bporter:2012-6:dsl.md",{"user":1533,"name":1534},{"_path":1568,"title":1569,"description":1570,"image":1571,"publishDate":1572,"tags":1573,"_id":1576,"author":1577},"/bporter/2019-3/animator","Friz: A flexible animation controller for JUCE","As is often the case, I found myself working on a personal project and had some UI elements that really wanted to have some life to them on the screen.","/bporter/2019-3/img/animator.png","2019-03-01",[1500,1574,1575],"ui","c++","content:bporter:2019-3:animator.md",{"user":1533,"name":1534},{"_path":1579,"title":1580,"description":1581,"image":1582,"publishDate":1583,"tags":1584,"_id":1587,"author":1588},"/bporter/2019-4/aesannounce","Art+Logic In the Real World","There are a few events coming up in the next few weeks where A+L will have people in attendance. If you're going to be there or nearby, please get in touch and we'll meet up.","/bporter/2019-4/img/aesLogo.jpg","2019-04-01",[1585,1586],"a+l","event","content:bporter:2019-4:aesAnnounce.md",{"user":1533,"name":1534},{"_path":1590,"title":1591,"description":1592,"image":1593,"publishDate":1594,"tags":1595,"_id":1596,"author":1597},"/bporter/2020-10/reanimated","Re-animated","Last year, I posted here about an animation control framework called 'Friz' that works within the JUCE Application Framework.","/bporter/2020-10/img/module.png","2020-10-01",[1500,1574,1575],"content:bporter:2020-10:reanimated.md",{"user":1533,"name":1534},{"_path":1599,"title":1600,"description":1601,"image":1602,"publishDate":1572,"tags":1603,"_id":1604,"author":1605},"/bstevens/2019-3","Coding the Impossible","As you can see on the Art+Logic website, our slogan is Coding the \"impossible.\"®","/bstevens/2019-3/img/impossible.png",[1585],"content:bstevens:2019-3:index.md",{"user":1606,"name":1607},"bstevens","Ben Stevens",{"_path":1609,"title":1610,"description":1611,"publishDate":1612,"tags":1613,"_id":1615,"author":1616},"/ckeefer/2013-1/misc","JS Hints & Shortcuts","During the course of any complex project (and even many simple ones), on the way to accomplish the actual goal, you're certain to encounter any number of small hurdles along the way - little problems which need to be resolved for the bigger picture to come into focus.","2013-09-01",[1614],"js","content:ckeefer:2013-1:misc.md",{"user":1617,"name":1618},"ckeefer","Christopher Keefer",{"_path":1620,"title":1621,"description":1622,"publishDate":1623,"tags":1624,"image":1629,"_id":1630,"author":1631},"/ckeefer/2013-2/xslt","XML and XSLT","Not terribly long ago, XML was the darling of the web. HTML4 was reformulated as XHTML 1.0, SOAP messages were XML, and let us not forget XMLHttpRequest.","2013-10-08",[1625,1626,1627,1628],"data-formats","xml","xsl","xslt","/ckeefer/2013-2/img/xslt-processing.png","content:ckeefer:2013-2:xslt.md",{"user":1617,"name":1618},{"_path":1633,"title":1634,"description":1635,"publishDate":1636,"tags":1637,"image":1640,"_id":1641,"author":1642},"/ckeefer/2013-3/ajax-upload","Ajax Upload Part I: Framed (and jQuery Deferred)","Inevitably, people want their files on the Internet. If your project is about cute cats, someone will task you with allowing users to upload photos of their cats, videos of their cats, long rambling audio clips in which they attempt to convince their cat to stop attacking the microphone, etcetera. If your project is about the nature and proclivities of mold, someone, somewhere will want to share detailed photographic evidence of their mold problem. The need to upload files is a given.","2013-03-20",[1614,1638,1639],"jquery","html5","/ckeefer/2013-3/img/upframe.jpg","content:ckeefer:2013-3:ajax-upload.md",{"user":1617,"name":1618},{"_path":1644,"title":1645,"description":1646,"publishDate":1647,"tags":1648,"_id":1650,"author":1651},"/ckeefer/2013-4/teaching-programming","Can (and Should) Everyone Learn to Program?","Fair warning: The following article is long, rambly, and contains no code. It does, however, contain some rumination on the idea that everyone can and should learn to program.","2013-12-03",[1649],"programming","content:ckeefer:2013-4:teaching-programming.md",{"user":1617,"name":1618},{"_path":1653,"title":1654,"description":1655,"publishDate":1656,"tags":1657,"image":1659,"_id":1660,"author":1661},"/ckeefer/2013-5/ajax-uploader","Ajax Upload XHR2, Take 2","It's a pleasure to be able to interact with files in the browser at long last, isn't it? Reading files in without needing to bounce them against the server first opens up a lot of possibilities - and getting progress from a chunked ajax upload is miles away from the indeterminate form uploads of days past.","2014-02-19",[1638,1614,1658],"xhr2","/ckeefer/2013-5/img/html5.jpg","content:ckeefer:2013-5:ajax-uploader.md",{"user":1617,"name":1618},{"_path":1663,"title":1664,"description":1665,"publishDate":1666,"tags":1667,"_id":1668,"author":1669},"/ckeefer/2013-07/anchors-hash","Anchors, Hash Sign, javascript:void(0)","So, you've got a link that, in reality, is just a click target for performing some javascript function. You want the appearance of a standard anchor link, but if it's not performing the intended function, should it really be an anchor? And if so, what should we fill that 'href' attribute in with?","2013-07-29",[1614],"content:ckeefer:2013-07:anchors-hash.md",{"user":1617,"name":1618},{"_path":1671,"title":1672,"description":1673,"publishDate":1674,"_id":1675,"author":1676},"/ckeefer/2013-07/static-vmware-host","Static Hosting with VMWare","Virtualization is one of the many benefits of the excess (metaphorical) horsepower available to us with modern hardware. Need to test against (Windows XP/7/8/NT || Fedora || Mint || Ubuntu || FreeBSD || MacOSX || etc)? Fire up the VM. Need a Linux environment for the packages your server relies on, but need to test in the iPad simulator? VM's to the rescue.","2013-07-26","content:ckeefer:2013-07:static-vmware-host.md",{"user":1617,"name":1618},{"_path":1678,"title":1679,"description":1680,"publishDate":1681,"tags":1682,"_id":1684,"author":1685},"/ckeefer/2013-08/fullproof-fulltext-search","Client-side Fulltext Searching with Fullproof","Recently, I was engaged in a genial argument with a friend of an older generation, each of us taking an opposing stance on some obscure trivia neither of us was entirely certain about - but which we were both ready to defend with all the wit and rhetoric at our disposal. When we had finally exhausted all attempts to make the other budge on the matter, we turned to an authoritative 3rd-party source to lay the matter to rest for us - a Google search.","2013-08-29",[1683,1628],"search","content:ckeefer:2013-08:fullproof-fulltext-search.md",{"user":1617,"name":1618},{"_path":1687,"title":1688,"description":1689,"publishDate":1690,"tags":1691,"_id":1692,"author":1693},"/ckeefer/2013-11/jquery-ajax-blobs","jQuery Ajax Blobs and Array Buffers","A big part of what makes jQuery a regular part of so many web projects is the clean interface it offers us for a number of sometimes messy built-in aspects of javascript. The most obvious is the DOM interface; and in second place, jquery ajax and its various shorthand methods. Abstracting away the difference between ActiveXObject and XMLHttpRequest is one of the most obvious benefits - but even if you don't need to worry about supporting old versions of IE, you might well enjoy the clean, object-based, promise-returning interface that jquery ajax offers.","2013-11-21",[1614,1638],"content:ckeefer:2013-11:jquery-ajax-blobs.md",{"user":1617,"name":1618},{"_path":1695,"title":1696,"description":1697,"publishDate":1698,"tags":1699,"_id":1701,"author":1702},"/ckeefer/2013-12/deploying-with-git","Deploying Websites with Git","Deploying your webapp is an important part of the web development equation - your client's site isn't going to attract a lot of attention sitting in your local dev directory. Deployment concerns tend to fall to the bottom of the priority list, though, and the end result tends to be kludgy, hastily thrown-together deployment scripts; and because they are so kludgy and, often, time consuming, when time crunches threaten, a developer may resort to making changes directly on the remote server that need to be (but sometimes never are) backported to the code living in your version control.","2013-12-23",[1700],"git","content:ckeefer:2013-12:deploying-with-git.md",{"user":1617,"name":1618},{"_path":1704,"title":1705,"description":1706,"publishDate":1707,"tags":1708,"image":1710,"_id":1711,"author":1712},"/ckeefer/2014-1/still-using-php","Still Using PHP?","Poor PHP. It's so lonely and unloved these days.","2014-01-29",[1709],"php","/ckeefer/2014-1/img/php.jpg","content:ckeefer:2014-1:still-using-php.md",{"user":1617,"name":1618},{"_path":1714,"title":1715,"description":1716,"publishDate":1717,"tags":1718,"image":1720,"_id":1721,"author":1722},"/ckeefer/2014-2/ajax-upload-2","Ajax Upload Part II: XHR2 (and FileReader)","So, the client has told you their users should be able to upload their drunken party pictures for all the internet to see. \"We want the very best experience possible,\" they tell you. \"Simple, seamless - maybe using that new html5 thing I've heard so much about.\"","2013-04-09",[1614,1719],"xmlhttprequest","/ckeefer/2014-2/img/html5.jpg","content:ckeefer:2014-2:ajax-upload-2.md",{"user":1617,"name":1618},{"_path":1724,"title":1725,"description":1726,"publishDate":1727,"tags":1728,"_id":1730,"author":1731},"/ckeefer/2014-3/customgmapsinfowindow","Custom Google Maps Info Windows","When it comes time to relate the ephemeral world of data to the physical world, Maps are key in both enterprise and consumer applications. Whatever else you might think of it, Google Maps tends to be the default option - certainly, its the only one I've ever had clients ask for by name.","2014-02-26",[1614,1729],"google-maps","content:ckeefer:2014-3:customgmapsinfowindow.md",{"user":1617,"name":1618},{"_path":1733,"title":1734,"description":1735,"publishDate":1736,"tags":1737,"_id":1739,"author":1740},"/ckeefer/2014-4/hidden-options","Hidden Options: A Workaround","Here's the situation: You've got a select. Maybe a whole bunch of selects, with a ton of options each (metric ton - let's keep our imaginary hyperbolic units straight here); and these are meant to be complex interactive elements, with options made visible or not as some programmatic condition dictates.","2014-04-23",[1738,1614,1638],"how-to","content:ckeefer:2014-4:hidden-options.md",{"user":1617,"name":1618},{"_path":1742,"title":1743,"description":1744,"publishDate":1745,"tags":1746,"_id":1747,"author":1748},"/ckeefer/2014-5/cgwin2","Custom Google Info Windows: Updated, Live","April 30, 2014 at 3:22 am Remy says:","2014-05-09",[1614,1729],"content:ckeefer:2014-5:cgwin2.md",{"user":1617,"name":1618},{"_path":1750,"title":1751,"description":1752,"publishDate":1753,"tags":1754,"image":1757,"_id":1758,"author":1759},"/ckeefer/2014-6/backbonesocketsync","Websockets for Backbone","Backbone's had some of its thunder stolen lately by trendier frameworks like Meteor and Angular; for good reason, in most cases, as without the prosthetic functionality offered by the likes of Marionette, Backbone's view handling (amongst a few other lacks and warts) is really just 'roughed in'.","2014-06-25",[1614,1755,1756],"websockets","backbone","/ckeefer/2014-6/img/WebsocketsPlusBackbone.png","content:ckeefer:2014-6:backbonesocketsync.md",{"user":1617,"name":1618},{"_path":1761,"title":1762,"description":1763,"publishDate":1764,"tags":1765,"_id":1766,"author":1767},"/ckeefer/2014-7/promises","It's a (jQuery-style) Promise","Way back when I brought up the topic of promises (particularly, jQuery Deferred), and I promised we would come back to the topic someday.","2014-10-16",[1614,1638],"content:ckeefer:2014-7:promises.md",{"user":1617,"name":1618},{"_path":1769,"title":1770,"description":1771,"publishDate":1772,"tags":1773,"_id":1774,"author":1775},"/ckeefer/2014-8/behold-views","Behold! (JavaScript Views)","JavaScript has the propensity to be very untidy - if you let it, it will sprawl all over the place. Hundreds of global variables scattered across dozens of files, messy half-measures towards object-orientation, mixed in seemingly at random with ungrouped functions - anyone who's had a client bring them a failed project from some other development team knows just how bad it can get.","2015-01-07",[1614],"content:ckeefer:2014-8:behold-views.md",{"user":1617,"name":1618},{"_path":1777,"title":1778,"description":1779,"publishDate":1780,"tags":1781,"image":1782,"_id":1783,"author":1784},"/ckeefer/2015-1/writeonce","Write Once, Debug Everywhere","It's pretty seldom that anyone mentions web pages these days, other than in historical reference to days long gone by (yes, a whole few years ago). Web sites, sure, but not if what is really wanted is to replace something that, not so long ago, would have been some native code for a smartphone (or a little further back still, a desktop computer). Generally speaking, the most common term tripping from client's lips these days is 'web applications' - or webapps, because who has time for spaces and proper spelling, amirite?","2015-02-02",[1614],"/ckeefer/2015-1/img/html5java.jpg","content:ckeefer:2015-1:writeonce.md",{"user":1617,"name":1618},{"_path":1786,"title":1787,"description":1788,"publishDate":1789,"tags":1790,"_id":1791,"author":1792},"/ckeefer/2015-2/js-frameworks","The What and Why of Javascript Frameworks","JavaScript has the propensity to be very untidy if you let it be. This isn't a problem unique to JavaScript, of course - many other languages suffer from a lack of native organization, especially for specific tasks.","2015-05-29",[1614],"content:ckeefer:2015-2:js-frameworks.md",{"user":1617,"name":1618},{"_path":1794,"title":1795,"description":1796,"publishDate":1797,"tags":1798,"_id":1801,"author":1802},"/ckeefer/2015-3/emailvalidation","Email Validation with Django and python-social-auth","When it comes to user accounts, the standard litmus test is email validation. Besides the immediate benefits - of offering us a straightforward unique identifier for users, and making it more difficult to automate creating a mass of accounts on our service - by requiring that each account have an email address and interact therewith to confirm the addresses validity, it also offers us the chance to associate a known-working email account with a user account. This is important for transactional emails such as password resets or for potential two-factor authentication use... and if you're a little less ethical, for sending marketing desirable and informative emails about interesting products and services.","2015-07-23",[1799,1800],"python","django","content:ckeefer:2015-3:EmailValidation.md",{"user":1617,"name":1618},{"_path":1804,"title":1805,"description":1806,"publishDate":1807,"tags":1808,"_id":1809,"author":1810},"/ckeefer/2015-5/file-reader-chunking","FileReader Chunking and Base64 DataURLs","In a hurry? You can now use our HUp jquery plugin to read files in a chunked fashion as data URLs. Hooray!","2015-12-15",[1614,1638],"content:ckeefer:2015-5:file-reader-chunking.md",{"user":1617,"name":1618},{"_path":1812,"title":1813,"description":1814,"publishDate":1815,"tags":1816,"_id":1817,"author":1818},"/ckeefer/2016-1/ajaxbinarycaching","Caching Binary Data With jQuery Ajax and IndexedDB","After long, grueling months (years? or does it only feel like years?), your web application nears completion. It is tightly coded, well documented, works across all modern browsers, and is well received by your beta testers. It's nearly time to go live, and a smile of pure relief plays upon your lips... and freezes into a rictus grin when your client turns to you, and asks, \"so, hey, can we speed up the dynamic cat pic loading? Especially when I close the browser and come back to it later. I think that's really key to the whole application.\"","2016-04-25",[1614,1638],"content:ckeefer:2016-1:ajaxBinaryCaching.md",{"user":1617,"name":1618},{"_path":1820,"title":1821,"description":1822,"publishDate":1823,"tags":1824,"_id":1825,"author":1826},"/ckeefer/2016-2/paymentprocessing","Payment Processing with Braintree","You've built the web application of the century, and the users have rightly flooded to it. Cat pictures for everyone!","2016-05-11",[1800,1614,1638,1799],"content:ckeefer:2016-2:paymentprocessing.md",{"user":1617,"name":1618},{"_path":1828,"title":1829,"description":1830,"publishDate":1831,"tags":1832,"_id":1833,"author":1834},"/ckeefer/2016-3/djangochannels1","Django Channels: From the Ground Up - Part 1","You stare mournfully into the mass of code you've inherited. At some point, it's clear, the requirements called for the server to push information to the client, because there's an unholy mix of Server-Side Events, long-polling, hidden iframes and even a Java applet in there, all supporting some level of long-term connectivity with the server. It's almost fascinating in its barely functional hideousness, and you would be inclined to leave well enough alone... except for the new feature specifications you've been assigned, which require the client to be able to send data back to the server in response to the received events, in as close to real-time as you can get.","2016-06-13",[1800,1799,1755],"content:ckeefer:2016-3:djangoChannels1.md",{"user":1617,"name":1618},{"_path":1836,"title":1837,"description":1838,"publishDate":1839,"tags":1840,"_id":1841,"author":1842},"/ckeefer/2016-4/djangochannels2","Django Channels: From the Ground Up - Part 2","Last time, we decided to embark on a brave new adventure and give our Django framework a big upgrade with the inclusion of Django Channels. We got just far enough to get the development server running, but while this may be an adequate start, it's better to develop against something like what we intend to deploy, right?","2016-06-15",[1800,1799,1755],"content:ckeefer:2016-4:djangochannels2.md",{"user":1617,"name":1618},{"_path":1844,"title":1845,"description":1846,"publishDate":1847,"tags":1848,"_id":1849,"author":1850},"/ckeefer/2016-6/gofetch1","Go Fetch! (JavaScript Fetch API)","Long ago, we briefly brushed upon the topic of what has made jQuery such a valuable part of the web developer's toolset for such a long time - namely, a cleaner interface for interacting with the DOM, and the $.ajax abstraction over XMLHttpRequest.","2016-10-03",[1614,1638,1462],"content:ckeefer:2016-6:goFetch1.md",{"user":1617,"name":1618},{"_path":1852,"title":1853,"description":1854,"publishDate":1855,"tags":1856,"_id":1857,"author":1858},"/ckeefer/2016-7/gofetch2","Go Fetch 2! (JavaScript Fetch API)","Last time we discussed the Fetch API in general, taking a look at how it differed from the XMLHttpRequest API, and some of its advantages. Today, we're going to take a look at a little library that you can include in your projects today that offers you localStorage caching for the Fetch API.","2016-10-10",[1614,1638,1462],"content:ckeefer:2016-7:goFetch2.md",{"user":1617,"name":1618},{"_path":1860,"title":1861,"description":1862,"publishDate":1863,"tags":1864,"_id":1867,"author":1868},"/ckeefer/2016-8/herokupdf","Generating PDFs: wkhtmltopdf & Heroku","So, it has come to this.","2016-12-21",[1865,1866,1799],"heroku","pdf","content:ckeefer:2016-8:HerokuPDF.md",{"user":1617,"name":1618},{"_path":1870,"title":1871,"description":1872,"publishDate":1873,"tags":1874,"_id":1875,"author":1876},"/ckeefer/2017-1/downloadingclientsidecontent","Downloading Client-side Generated Content","A young developer, new to the Tao of the client-side, comes to a Master of the way, and speaks thusly: \"Oh Master, our application nears completion; and lo, cat pics can be drawn upon, and captions fixated thereto, for the creation of humour and the bounteous enjoyment of our users.\"","2017-02-06",[1614],"content:ckeefer:2017-1:downloadingclientsidecontent.md",{"user":1617,"name":1618},{"_path":1878,"title":1879,"description":1880,"publishDate":1881,"tags":1882,"_id":1885,"author":1886},"/ckeefer/2017-2/morepwatoya-part1","More PWA to Ya! (Progressive Web Apps, Part 1)","It's project kickoff time, and you're having a conversation with your client about what form the application will take:","2017-02-01",[1883,1884,1462],"pwa","mobile","content:ckeefer:2017-2:MorePWAToYa-Part1.md",{"user":1617,"name":1618},{"_path":1888,"title":1889,"description":1890,"tags":1891,"publishDate":1892,"_id":1893,"author":1894},"/ckeefer/2017-3/morepwatoya-part2","More PWA to Ya! (Progressive Web Apps, Part 2)","Last time, we got into the nitty gritty on how to make your web application into a Progressive Web Application (PWA to it's friends). I promised we'd dig even deeper this time, and show you how to make your web app a little more 'native' on Android - and how to deal with iOS Safari's special snowflake syndrome.",[1884,1883,1462],"2017-03-01","content:ckeefer:2017-3:MorePWAToYa-Part2.md",{"user":1617,"name":1618},{"_path":1896,"title":1897,"description":1898,"image":1899,"publishDate":1900,"tags":1901,"_id":1903,"author":1904},"/ckeefer/2019-1/unlockingwebaudio","Unlocking Web Audio","\"It's going to be the coolest thing ever.\"","/ckeefer/2019-1/img/featured_image.jpg","2019-01-01",[1614,1902],"audio","content:ckeefer:2019-1:UnlockingWebAudio.md",{"user":1617,"name":1618},{"_path":1906,"title":1907,"description":1908,"publishDate":1909,"image":1910,"tags":1911,"_id":1913,"author":1914},"/ckeefer/2020-1/why-vue","Why Vue","Why choose Vue over any other front-end framework?","2020-01-01","/ckeefer/2020-1/img/vue-wall.jpg",[1614,1912],"vue","content:ckeefer:2020-1:Why Vue.md",{"user":1617,"name":1618},{"_path":1916,"title":1917,"description":1918,"tags":1919,"image":1922,"publishDate":1923,"_id":1924,"author":1925},"/ckeefer/2024-3/e2e_testing","E2E Testing: To What End?","Friend, can we agree that tests are a good idea? I won't scorn you for sometimes omitting them - time and budget constraints are what they are, and even the best intentioned of us sometimes have to just give our projects a lick and a promise. \"Proper test coverage soon\", you sweetly croon as you rock it to sleep, the knowledge that you're telling a dark, terrible lie twisting you up inside. Maybe you could just scrape enough budget together for some simple unit tests? Then, at least, you'd have \"tests\", right?",[1483,1482,1920,1921],"e2e","playwright","/ckeefer/2024-3/img/E2E_Testing_2024.png","2024-06-15","content:ckeefer:2024-3:e2e_testing.md",{"user":1617,"name":1618},{"_path":1927,"title":1928,"description":1929,"tags":1930,"image":1932,"publishDate":1933,"_id":1934,"author":1935},"/ckeefer/2024-7/vpubsub","Vue 3 Pub / Sub: All aboard the (event) bus","We like Vue at A+L. We think it's one of the best frontend frameworks, and a great choice pretty much anywhere you might otherwise be tempted to use React.",[1614,1912,1931],"pub/sub","/ckeefer/2024-7/img/event_bus.png","2024-08-15","content:ckeefer:2024-7:VPubSub.md",{"user":1617,"name":1618},{"_path":1937,"title":1938,"description":1939,"publishDate":1940,"tags":1941,"_id":1942,"author":1943},"/cmacksey/2012-5/php-musings","PHP Musings","Ran into an interesting, but thorough, rant the other day - PHP: A Fractal of Bad Design. The part that grabbed me the most was the analogy at the beginning, which was all too perfect:","2012-05-07",[1709],"content:cmacksey:2012-5:php-musings.md",{"user":1944,"name":1945},"cmacksey","Chris Macksey",{"_path":1947,"title":1948,"description":1949,"publishDate":1950,"image":1951,"author":1952,"tags":1953,"_id":1959},"/cperez/2026-06-17/xamarin-to-maui","Migrating a Xamarin Medical Application to .NET MAUI","A widely used medical reference application built with Xamarin had become increasingly difficult to maintain as platform support deadlines approached. The client needed to modernize the application before operating system changes and framework deprecations created larger compatibility risks.","2026-06-22","/cperez/2026-06-17/img/xamarin-to-maui.png",{"name":13,"user":14},[1954,1955,1956,1957,1958,1884],"legacy modernization","xamarin",".net","maui","app migration","content:cperez:2026-06-17:xamarin-to-maui.md",{"_path":1961,"title":1962,"description":1963,"publishDate":1964,"image":1965,"author":1966,"tags":1967,"_id":1969},"/cperez/2026-06-25/ai_makes_modernization_feasible","How AI-Assisted Legacy Modernization Reduces Cost, Risk, and Project Timelines","Many organizations know they need to modernize their legacy applications. They also know why they haven't.","2026-06-25","/cperez/2026-06-25/img/ai_makes_modernization_feasible.png",{"name":13,"user":14},[1954,18,1968,17],"ai","content:cperez:2026-06-25:ai_makes_modernization_feasible.md",{"_path":1971,"title":1972,"description":1973,"publishDate":1974,"image":1975,"author":1976,"tags":1977,"_id":1982},"/cperez/2026-06-30/how-ceos-should-evaluate-ai-investments","How Should CEOs Evaluate AI Investments?","CEOs should evaluate AI investments by asking whether the investment improves a measurable business outcome, changes a real workflow, keeps humans appropriately involved, has a realistic path to production, and creates value that outweighs cost and risk.","2026-06-30","/cperez/2026-06-30/img/how-ceos-should-evaluate-ai-investments.jpg",{"name":13,"user":14},[1978,1979,1980,1968,1981],"agentic ai","ai investment","humans in the loop","software development","content:cperez:2026-06-30:how-ceos-should-evaluate-ai-investments.md",{"_path":1984,"title":1985,"description":1986,"publishDate":1987,"image":1988,"author":1989,"tags":1990,"_id":1991},"/cperez/2026-07-02/hidden-costs-of-legacy-software","What Are the Hidden Costs of Legacy Software?","Legacy software is rarely “bad” software.","2026-07-02","/cperez/2026-07-02/img/hidden-costs-of-legacy-software.jpg",{"name":13,"user":14},[1954,20],"content:cperez:2026-07-02:hidden-costs-of-legacy-software.md",{"_path":1993,"title":1994,"description":1995,"publishDate":1996,"image":1997,"author":1998,"tags":1999,"_id":2002},"/cperez/2026-07-07/why-ai-projects-fail","Why Do Most AI Projects Fail?","AI projects rarely fail because the model was not powerful enough.","2026-07-07","/cperez/2026-07-07/img/why-ai-projects-fail.jpg",{"name":13,"user":14},[1968,2000,1981,2001],"ethics","vibe coding","content:cperez:2026-07-07:why-ai-projects-fail.md",{"_path":2004,"title":2005,"description":2006,"publishDate":2007,"image":2008,"author":2009,"tags":2010,"_id":2013},"/cperez/2026-07-09/5-rs-application-modernization-legacy-software","Art+Logic’s 5 Rs of Application Modernization: How to Choose the Right Path for Legacy Software","Legacy software creates a strange kind of tension.","2026-07-09","/cperez/2026-07-09/img/5-rs-application-modernization-legacy-software.jpg",{"name":13,"user":14},[2011,2012,1968,19],"5-rs","legacy","content:cperez:2026-07-09:5-rs-application-modernization-legacy-software.md",{"_path":5,"title":9,"description":10,"publishDate":6,"image":11,"author":2015,"tags":2016,"_id":1449},{"name":13,"user":14},[16,17,18,19,20],{"_path":2018,"title":2019,"description":2020,"publishDate":2021,"image":2022,"author":2023,"tags":2024,"_id":2029},"/cperez/2026-07-21/building-digital-health-platforms-beyond-samd","Beyond SaMD: Building a Digital Health Platform That Can Evolve","A medical application can work exactly as designed and still fall short of what the organization needs next.","2026-07-21","/cperez/2026-07-21/img/building-digital-health-platforms-beyond-samd.jpg",{"name":13,"user":14},[2025,2012,16,2026,2027,1955,2028],"samd","biomedical","healthcare",".net maui","content:cperez:2026-07-21:building-digital-health-platforms-beyond-samd.md",{"_path":2031,"title":2032,"description":2033,"publishDate":2034,"image":2035,"author":2036,"tags":2037,"_id":2041},"/cperez/2026-07-23/why-ai-agents-need-software-developers","Beyond the Chatbot: Your AI Agent Is a Software Product, Not a Prompt","The AI-agent demo usually looks simple.","2026-07-23","/cperez/2026-07-23/img/why-ai-agents-need-software-developers.jpg",{"name":13,"user":14},[1968,1980,1979,2038,1978,2039,1512,2040],"chatbots","ai agents","ai development","content:cperez:2026-07-23:why-ai-agents-need-software-developers.md",{"_path":2043,"title":2044,"description":2045,"publishDate":2046,"tags":2047,"_id":2049,"author":2050},"/dpopowich/2021-07-30/data-collector","Asynchronous Python - A Real World Example","A dive into a real example of async Python usage.","2021-07-30",[1799,1738,2048],"async","content:dpopowich:2021-07-30:data-collector.md",{"user":2051,"name":2052},"dpopowich","Daniel Popowich",{"_path":2054,"title":2055,"description":2056,"tags":2057,"image":2059,"publishDate":2060,"_id":2061,"author":2062},"/dpopowich/2023-8/postgres-pubsub","Using PostgreSQL for Pub/Sub","A+L has been working on a Single Page Application (SPA) wherein our client's users take on the role of Staff Users (think: project managers) as they aid their Customer Users in using the application to complete a complex project.",[2058,1799,2048],"postgresql","/dpopowich/2023-8/img/psql_pub_sub.png","2024-04-15","content:dpopowich:2023-8:postgres-pubsub.md",{"user":2051,"name":2052},{"_path":2064,"title":2065,"description":2066,"tags":2067,"image":2070,"publishDate":2071,"_id":2072,"author":2073},"/ewahl/2025-05/escape_deployment_hell","Escape Deployment Hell: IaC, CDK, Ephemeral Environments, and the Pragmatic Path to Platform Power","Another Friday afternoon, another deployment fire. If this sounds familiar, you're not alone. On too many projects, the chasm between application code and infrastructure management breeds manual configuration nightmares, crippling complexity, and agonizingly slow development cycles. But what if your team could sidestep this chaos, focusing on building features instead of constantly battling deployment gremlins?",[2068,2069,1799],"devops","aws","/ewahl/2025-05/img/deployment_hell.png","2025-05-13","content:ewahl:2025-05:escape_deployment_hell.md",{"user":2074,"name":2075},"ewahl","Edward F. Wahl",{"_path":2077,"title":2078,"description":2079,"publishDate":2080,"image":2081,"tags":2082,"_id":2083,"author":2084},"/ewahl/2025-06/argued_with_ai","I Argued With an AI for 20 Minutes About Async Code &mdash; And I'm Surprisingly Happy","If you have ever spent twenty minutes debating an obscure AWS Lambda invocation pattern with an AI, you might question your life choices. But here I am: amused by the wasted time but ultimately happy with the outcome and understanding I gained.","2026-06-01","/ewahl/2025-06/img/argued_with_ai.png",[2068,2069,1799],"content:ewahl:2025-06:argued_with_ai.md",{"user":2074,"name":2075},{"_path":2086,"title":2087,"description":2088,"tags":2089,"image":2090,"publishDate":1583,"_id":2091,"author":2092},"/jbagley/2019-4/makingspectrogramsinjuce","Making Spectrograms in JUCE","Art+Logic's Incubator project has made a lot of progress. In a previous post I mentioned that Dr. Scott Hawley's technique to classify audio involved converting audio to an image and using a Convolution Neural Network (CNN) to classify the audio based on this image. That image is a spectrogram. I'm going to go into some detail about what we do to create one, and why to the best of my ability.",[1500,1575,1902],"/jbagley/2019-4/img/Fortissimo_Trumpet_Ensemble_Matrix_Swells_61.wav-2048x1700.png","content:jbagley:2019-4:MakingSpectrogramsInJUCE.md",{"user":2093,"name":2094},"jbagley","Jason Bagley",{"_path":2096,"title":2097,"description":2098,"tags":2099,"image":2101,"publishDate":2102,"_id":2103,"author":2104},"/jbagley/2021-07/softwaresenescence","Legacy Vulnerabilities AKA Software Senescence","Does your business still have an XT computer in the back office because it's\nrunning that one version of some database software that your business depends\non? Yeah, we know there is. Most modern software doesn't work like that.",[2012,2100],"project-management","/jbagley/2021-07/img/old_software_to_new.jpg","2021-07-01","content:jbagley:2021-07:SoftwareSenescence.md",{"user":2093,"name":2094},{"_path":2106,"title":2107,"description":2108,"tags":2109,"image":2111,"publishDate":2112,"_id":2113,"author":2114},"/jbagley/2021-08-01/accuratetiming","Accurate Timing","In many tasks we need to do something at given intervals of time. The most obvious ways may not give you the best results.",[1575,2110],"timing","/jbagley/2021-08-01/img/accurateTiming.jpg","2021-08-01","content:jbagley:2021-08-01:AccurateTiming.md",{"user":2093,"name":2094},{"_path":2116,"title":2117,"description":2118,"tags":2119,"image":2123,"publishDate":2124,"_id":2125,"author":2126},"/jbagley/2023-06-01/universal_ffmpeg_custom_builds","Building Universal FFmpeg Custom Binaries","I am using a very pared down set of FFMpeg features for a macOS project that I\nbuild into a custom library. I had a script set up to configure the build which\nworked fine on my Intel based MacBook Pro. Then I upgraded to an Apple Silicon\nMacBookPro and wanted to run natively, or at least see what happened when I\ndid. To build, FFMpeg uses autoconf which produces a makefile that then handles\nthe build.",[2120,2121,2122,1498],"c","bash","ffmpeg","/jbagley/2023-06-01/img/header.png","2024-04-01","content:jbagley:2023-06-01:Universal_FFMPEG_custom_builds.md",{"user":2093,"name":2094},{"_path":2128,"title":2129,"description":2130,"publishDate":2131,"image":2132,"tags":2133,"_id":2137,"author":2138},"/jbagley/2025-08/a_developers_primer_on_apple_tracking_transparency","A Primer on Apple's App Tracking Transparency","If an app tracks user activity, Apple requires them to declare all information they collect as well as whether that data is linked or tracked. This includes collection by the app itself and any third parties the app uses. The app owner is responsible for knowing and correctly reporting privacy information for all components in the app.","2026-05-22","/jbagley/2025-08/img/apple_app_transparency.png",[2134,2135,1497,2136],"app tracking transparency","att","macos","content:jbagley:2025-08:a_developers_primer_on_apple_tracking_transparency.md",{"user":2093,"name":2094},{"_path":2140,"title":2141,"description":2142,"tags":2143,"image":2147,"publishDate":2148,"_id":2149,"author":2150},"/jestep/2023-3/fastapi","FastAPI: A High-Performance Python Framework for Rapid Web Development","FastAPI is a modern and high-performance Python web framework designed specifically for building APIs and web applications quickly and efficiently. Developed by Sebastián Ramírez and first released in 2018, FastAPI has rapidly gained traction in the developer community thanks to its focus on providing key features for API and web app development with excellent performance.",[1799,2144,1800,2145,2146],"fastapi","flask","pyramid","/jestep/2023-3/img/header.png","2024-05-01","content:jestep:2023-3:fastapi.md",{"user":2151,"name":2152},"jestep","Jagger Estep",{"_path":2154,"title":2155,"description":2156,"publishDate":2157,"tags":2158,"image":2162,"_id":2163,"author":2164},"/nharrison/2012-07/core-data","Securing Your Core Data with Transformable Attributes","In order to store private data in an iOS Core Data database, there are several methods available for encryption, including:","2012-07-30",[2159,2160,1497,1512,2161],"core-data","encryption","objective-c","/nharrison/2012-07/img/superman.jpg","content:nharrison:2012-07:core-data.md",{"user":2165,"name":2166},"nharrison","Noah Harrison",{"_path":2168,"title":2169,"description":2170,"tags":2171,"publishDate":2176,"image":2177,"_id":2178,"author":2179},"/phendry/2019-3/restfromthebottomup","REST from the Bottom Up","The RESTful API has a funny place in the software development world: it's widely regarded as the best general-purpose pattern for building web application APIs, and yet it's also nebulous enough of a concept to cause endless disagreements within teams over exactly how to implement one.",[2172,2173,2174,2175],"rest","api","web","architecture","2019-10-01","/phendry/2019-3/img/feature_image.png","content:phendry:2019-3:RestFromTheBottomUp.md",{"user":2180,"name":2181},"phendry","Paul Hendry",{"_path":2183,"title":2184,"description":2185,"tags":2186,"publishDate":2102,"image":2187,"_id":2188,"author":2189},"/phendry/2021-06/smoothupgradestovue3","Smooth Upgrades to Vue 3","This post assumes basic familiarity with Vue.js v2.x.",[1614,1912,1738],"/phendry/2021-06/img/vue-transition.jpg","content:phendry:2021-06:SmoothUpgradesToVue3.md",{"user":2180,"name":2181},{"_path":2191,"title":2192,"description":2193,"image":2194,"tags":2195,"publishDate":2046,"_id":2196,"author":2197},"/phendry/2021-07-30/spotthevulndataranges","Spot the Vulnerability: Data Ranges and Untrusted Input","In 1997, a flaw was discovered in how Linux and Windows handled IP fragmentation, a Denial-of-Service vulnerability which allowed systems to be crashed remotely.","/phendry/2021-07-30/img/vulnerability.jpg",[1512,1462],"content:phendry:2021-07-30:SpotTheVulnDataRanges.md",{"user":2180,"name":2181},{"_path":2199,"title":2200,"description":2201,"tags":2202,"image":2203,"publishDate":2204,"_id":2205,"author":2206},"/phendry/2021-08-15/exploringdependenttypesinidris","Exploring Dependent Types in Idris","When I'm not coding the \"impossible\" at Art+Logic, I take a lot of interest in new programming technologies and paradigms; even if they're not yet viable for use in production, there can often be takeaways for improving your everyday code.",[1649],"/phendry/2021-08-15/img/dependent-types.jpg","2021-08-15","content:phendry:2021-08-15:ExploringDependentTypesInIdris.md",{"user":2180,"name":2181},{"_path":2208,"title":2209,"description":2210,"tags":2211,"image":2212,"publishDate":2213,"_id":2214,"author":2215},"/phendry/2021-10-30/spotthevulnloopsandtermconditions","Spot the Vulnerability: Loops and Terminating Conditions","In memory-unsafe languages like C, special care must be taken when copying untrusted data, particularly when copying it to another buffer. In this post, we'll spot and mitigate a past vulnerability in Linux's NTP daemon.",[1512,1462],"/phendry/2021-10-30/img/vulnerability-2.jpg","2021-10-30","content:phendry:2021-10-30:SpotTheVulnLoopsAndTermConditions.md",{"user":2180,"name":2181},{"_path":2217,"title":2218,"description":2219,"image":2220,"tags":2221,"publishDate":2222,"_id":2223,"author":2224},"/phendry/2022-07-21/migratingfromexpresstofastifypart1","Migrating from Express to Fastify, Part 1","Express.js has for years been the dominant lightweight Web framework for Node.js, but over time its development has stalled, with its latest major version (5.0) still in pre-release nearly eight years after its first alpha release. There's a lot to be said for this sort of stability in a foundational dependency for a project, but it's worth assessing whether the added features of competing frameworks are worth making a switch. In this article we'll be looking at Fastify in particular, to understand what it has to offer compared to Express and how difficult it is to migrate an existing Express project.","/phendry/2022-07-21/img/Migrating from Express to Fastify, Part 1.png",[1614,1462],"2023-12-01","content:phendry:2022-07-21:MigratingFromExpressToFastifyPart1.md",{"user":2180,"name":2181},{"_path":2226,"title":2227,"description":2228,"image":2229,"tags":2230,"publishDate":2231,"_id":2232,"author":2233},"/phendry/2022-07-28/migratingfromexpresstofastifypart2","Migrating from Express to Fastify, Part 2","In Part 1, we looked at the features of the Fastify Node.js Web framework compared to Express.js. In Part 2, we'll work through migrating an example Express.js application to Fastify.","/phendry/2022-07-28/img/Migrating from Express to Fastify, Part 2.png",[1614,1462],"2023-12-31","content:phendry:2022-07-28:MigratingFromExpressToFastifyPart2.md",{"user":2180,"name":2181},{"_path":2235,"title":2236,"description":2237,"tags":2238,"image":2239,"publishDate":2240,"_id":2241,"author":2242},"/phendry/2023-01-19/badcode","\"Bad\" Code (Or, Why Software Development is Hard)","Recently, the Dutch government open-sourced the iOS application for their \"DigiD\" authentication service. A tweet with a snippet of that source code, presumably making fun of it, blew up into a debate about whether mocking it is even justified. The amount of debate over such a simple snippet of code highlights, in my mind, just how tricky software development can be.",[1512,1462],"/phendry/2023-01-19/img/Bad Code.png","2024-01-15","content:phendry:2023-01-19:BadCode.md",{"user":2180,"name":2181},{"_path":2244,"title":2245,"description":2246,"image":2247,"publishDate":2248,"tags":2249,"_id":2250,"author":2251},"/phendry/2023-01-31/forgetaboutcodestyle","Forget About [Code] Style","Good code style, being highly subjective, is something often debated among developers. After all, we spend more time reading code than writing it, so it's worth making sure our code is styled to be as easy as possible to read and to understand. On the other hand, deciding upon and continuously enforcing a style is also time-consuming, and the benefits are near-impossible to quantify. Given that modern code formatting tools can fully automate the process, is it still worth fretting about style?","/phendry/2023-01-31/img/forget_style_header.png","2024-02-01",[1649],"content:phendry:2023-01-31:ForgetAboutCodeStyle.md",{"user":2180,"name":2181},{"_path":2253,"title":2254,"description":2255,"image":2256,"tags":2257,"publishDate":2258,"_id":2259,"author":2260},"/phendry/2023-04-02/semantichtml","Don't Give Up on Semantic HTML","Since the early days of the Web, there has been tension between the ideal of \"semantic HTML\" and the practical reality of designing complex page layouts, which often could not be achieved without inserting style concerns into the document. More recently, frameworks like Tailwind CSS have emerged which challenge the very idea that semantic HTML is an ideal to strive for, and which commit to thoroughly embedding style concerns into HTML documents. With modern CSS features however, semantic HTML is more achievable than ever, and I do think it remains a worthy goal.","/phendry/2023-04-02/img/Don't Give Up on Semantic HTML.png",[1649],"2024-03-01","content:phendry:2023-04-02:SemanticHtml.md",{"user":2180,"name":2181},{"_path":2262,"title":2263,"description":2264,"image":2265,"tags":2266,"publishDate":2267,"_id":2268,"author":2269},"/phendry/2023-05-16/doyouneedacsspreprocessor","Do You Need a CSS Preprocessor in 2023?","CSS preprocessors like Less, Sass and Stylus have long provided powerful features that vanilla CSS lacked: variables, nesting of rulesets, mixins, control flow constructs, etc. These days however, the feature gap is considerably narrower, and it's not so clear that the benefits of a preprocessor outweight the burdens of setting it up.","/phendry/2023-05-16/img/css_preprocessor_header.png",[1649],"2023-01-01","content:phendry:2023-05-16:DoYouNeedACSSPreprocessor.md",{"user":2180,"name":2181},{"_path":2271,"title":2272,"description":2273,"image":2274,"publishDate":2275,"tags":2276,"_id":2277,"author":2278},"/phendry/2023-07-28/dependencymanagement","Software Dependency Management: Best Practices","Leveraging third-party libraries and frameworks is essential in most modern software projects, and the projects we build at Art+Logic are no exception. The pressure on developers to rapidly deliver features is high, and there are so many commonalities in the details of each project (particularly in Web development) that a lot of development time can be saved by using well-designed libraries that handle the details.","/phendry/2023-07-28/img/dependency_header.png","2023-01-02",[1649],"content:phendry:2023-07-28:DependencyManagement.md",{"user":2180,"name":2181},{"_path":2280,"title":2281,"description":2282,"tags":2283,"publishDate":2286,"image":2287,"_id":2288,"author":2289},"/phendry/2023-11-06/frontendframeworksin2024","Frontend Frameworks in 2024: React, Svelte and Vue","Several years ago, Art+Logic settled on Vue.js as our preferred frontend Web framework. Now, in 2024, we feel it's time to revisit the frontend framework landscape to see how things have (or haven't) changed.",[1649,2284,2285,1912],"react","svelte","2024-05-15","/phendry/2023-11-06/img/frontend_frameworks_2024.png","content:phendry:2023-11-06:FrontendFrameworksIn2024.md",{"user":2180,"name":2181},{"_path":2291,"title":2292,"description":2293,"publishDate":2294,"tags":2295,"image":2298,"_id":2299,"author":2300},"/rbrubaker/2012-06/arduino-thermometer","Turn Your Mac into a Thermometer with Arduino","The topic of the Arduino came up around A&L's \"virtual water cooler\" last week. About a year and a half ago, I purchased a SparkFun Inventor's Kit for Arduino. The kit is a fun way for a hardware novice like me to get started and learn some basics. It comes with more than a dozen sample projects such as lighting LEDs, spinning a motor and generating audio.","2012-06-28",[2296,2297],"arduino","java","/rbrubaker/2012-06/img/arduino1.jpg","content:rbrubaker:2012-06:arduino-thermometer.md",{"user":2301,"name":2302},"rbrubaker","Ryan Brubaker",{"_path":2304,"title":2305,"description":2306,"publishDate":2307,"tags":2308,"_id":2311,"author":2312},"/rbrubaker/2012-06/coffe-backbone-1","Fun with CoffeeScript and Backbone.js : Part 1","CoffeeScript has been all the rage lately and I've been wanting to hop on board the bandwagon. I've also seen Backbone.js mentioned quite a bit and was even more intrigued after listening to this .NET Rocks podcast. I decided to convert some plain JavaScript code I had in a side project to use both CoffeeScript and Backbone.js and see how things went.","2012-06-06",[2309,2310,1639,1462],"backbone-js","coffeescript","content:rbrubaker:2012-06:coffe-backbone-1.md",{"user":2301,"name":2302},{"_path":2314,"title":2315,"description":2316,"publishDate":2317,"tags":2318,"_id":2319,"author":2320},"/rbrubaker/2012-06/coffee-backbone-2","Fun with CoffeeScript and Backbone.js : Part 2","In this post I’ll discuss the code that handles updating the UI.","2012-06-07",[2309,2310,1639,1462],"content:rbrubaker:2012-06:coffee-backbone-2.md",{"user":2301,"name":2302},{"_path":2322,"title":2323,"description":2324,"publishDate":2325,"tags":2326,"_id":2327,"author":2328},"/rbrubaker/2012-06/coffee-backbone-3","Fun with CoffeeScript and Backbone.js : Part 3","In this post I’ll discuss my thoughts on CoffeeScript and Backbone.js.","2012-06-08",[2309,2310,1639,1462],"content:rbrubaker:2012-06:coffee-backbone-3.md",{"user":2301,"name":2302},{"_path":2330,"title":2331,"description":2332,"publishDate":2333,"tags":2334,"_id":2335,"author":2336},"/rbrubaker/2012-07/prototypal-js","Prototypal vs. Functional Inheritance in JavaScript","If you ever found JavaScript's prototypal inheritance confusing, do yourself a favor and open this article, open a JavaScript console and code each example in the article. You will definitely come away with a better understanding of how prototypal inheritance works in JavaScript.","2012-07-11",[2310,1614],"content:rbrubaker:2012-07:prototypal-js.md",{"user":2301,"name":2302},{"_path":2338,"title":2339,"description":2340,"publishDate":2341,"tags":2342,"_id":2343,"author":2344},"/rbrubaker/2012-07/whither-pm","Whither Project Management?","When I was first asked to manage a project at Art & Logic, I had my reservations. Did I really want to start down a career path that led to less development? Would my skills as a developer go stale? My first few projects as a manager were solo projects so I still had plenty of development work and fortunately, I found myself to be a pretty easy person to manage. As time went on I started managing larger projects and with them came the responsibility to manage other developers. To my surprise I found project management to be rewarding and dare I say, even fun. It's very satisfying to work with clients, helping them define their visions and seeing those visions come to life.","2012-07-25",[2100],"content:rbrubaker:2012-07:whither-pm.md",{"user":2301,"name":2302},{"_path":2346,"title":2347,"description":2348,"tags":2349,"image":2352,"publishDate":1583,"_id":2353,"author":2354},"/scharette/2019-4/discover_machine_learning","Discover Machine Learning","Computers have been around for less than 100 years.  In that short period of time, some incredible things have happened:  they've been universally adopted so quickly that we have them in our houses.  In our cars.  Even in our pockets.  In the last 40 years, there have been many significant events when it comes to computers:",[2350,2351,1575],"machine-learning","neural-networks","/scharette/2019-4/img/discover_machine_learning.png","content:scharette:2019-4:discover_machine_learning.md",{"user":2355,"name":2356},"scharette","Stéphane Charette",{"_path":2358,"title":2359,"description":2360,"publishDate":2361,"image":2362,"tags":2363,"_id":2365,"author":2366},"/shuey/2012-05/baas","BaaS Offerings Continue to Grow","The makers of Simplenote recently introduced their Backend as a Service (BaaS) offering called Simperium that looks to compete in an increasingly crowded space with services like CloudMine, Kinvey, and Parse and to some extent with iCloud for iOS and OS X only apps. So just how crowded is this space? Back in February, Kinvey published their own map of the BaaS ecosystem that highlights different tiers of the ecosystem and various relationships between them.","2012-05-10","/shuey/2012-05/img/header.png",[2364],"baas","content:shuey:2012-05:baas.md",{"user":2367,"name":2368},"shuey","Steven Huey",{"_path":2370,"title":2371,"description":2372,"publishDate":2373,"tags":2374,"image":2376,"_id":2377,"author":2378},"/shuey/2012-05/cloud","Under the Sheets with iCloud and Core Data","Drew McCormack is writing a great series (Part 1, Part 2, Part 3) of posts about using iCloud for syncing Core Data managed data. It's harder than Apple lets on and Drew has done a great job of uncovering how this actually works.","2012-05-28",[1498,2375],"icloud","/shuey/2012-05/img/icloud.jpg","content:shuey:2012-05:cloud.md",{"user":2367,"name":2368},{"_path":2380,"title":2381,"description":2382,"publishDate":2383,"tags":2384,"_id":2386,"author":2387},"/shuey/2012-05/economics-android","The Economics of Android","If you haven't already do yourself a favor and head over to asymco.com to catch Horace Deidu's multi-post series on \"The Economics of Android\". Horace and Dan Benjamin discuss the series during this week's Critical Path podcast as well. Horace is a former analyst for Nokia and has been writing Asymco for a few years now. His analysis of the mobile industry and Apple's place within it in particular has been featured in publications such as Bloomberg and Forbes.","2012-05-17",[2385],"android","content:shuey:2012-05:economics-android.md",{"user":2367,"name":2368},{"_path":2389,"title":2390,"description":2391,"publishDate":1940,"tags":2392,"_id":2395,"author":2396},"/shuey/2012-05/iot","The Internet of Things and Big Data","I've been following the developments in the \"Internet of Things\" and Big Data / Open Data markets as new apps and tools are released and they look to be two exciting technologies on a collision course. With the advent of internet connected home appliances like Wattvision and Nest that provide real utility to the average home owner at reasonable prices along with crowd funded projects like Air Quality Egg or Twine we should see an explosion in the kinds and amount of useful and real-time or near real-time data that is available to anyone with a smartphone. Health metric or \"quantitative self\" tracking devices such as Fitbit, Jawbone Up, and the Pebble watch will fuel this data explosion as well.",[2393,2394],"big-data","iot","content:shuey:2012-05:iot.md",{"user":2367,"name":2368},{"_path":2398,"title":2399,"description":2400,"publishDate":2401,"tags":2402,"image":2404,"_id":2405,"author":2406},"/shuey/2012-05/rubymotion","RubyMotion Brings Ruby to iOS","RubyMotion is a new development toolchain that allows you to build iOS apps using Ruby created by Laurent Sansonetti, a former Apple engineer and contributor to the MacRuby project. It has garnered a lot of attention the past few weeks and some detailed reviews have already been written:","2012-05-14",[1497,2403],"ruby","/shuey/2012-05/img/logotype-icon.png","content:shuey:2012-05:rubymotion.md",{"user":2367,"name":2368},{"_path":2408,"title":2409,"description":2410,"publishDate":2411,"tags":2412,"image":2413,"_id":2414,"author":2415},"/shuey/2012-06/thoughts-ios6","A few thoughts on iOS 6","Apple made their session videos from WWDC 2012 available earlier this week in record time. It's nice to see since tickets for this years event sold out in under two hours. Apple has an iOS 6 Preview page touting some of the new features such as Siri's new abilities, tighter integration with Facebook, Photo Stream sharing, and things like iCloud tabs for Safari all of which look great.","2012-06-21",[1498,1497],"/shuey/2012-06/img/ios6.jpg","content:shuey:2012-06:thoughts-ios6.md",{"user":2367,"name":2368},{"_path":2417,"title":2418,"description":2419,"publishDate":2420,"tags":2421,"image":2423,"_id":2424,"author":2425},"/shuey/2012-07/mixer","A Simple Mixer Using AVFoundation","In iOS 4.0 Apple introduced the AV Foundation APIs that made working with audio and video media much easier than it had been in previous versions of iOS. Apple then brought these APIs to Mac OS X in OS X 10.7 \"Lion\". In this post I'll show how to use some of the APIs to create a simple four track mixer.","2012-07-02",[1498,2422,1497],"cocoa","/shuey/2012-07/img/mixer-screenshot.jpg","content:shuey:2012-07:mixer.md",{"user":2367,"name":2368},{"_path":2427,"title":2428,"description":2429,"publishDate":2430,"tags":2431,"image":2432,"_id":2433,"author":2434},"/shuey/2012-07/reset-button","The Reset Button","Horace Dediu of Asymco has been publishing some fantastic insights and analysis of the mobile market in the past few weeks. I linked to some of Dediu's analysis of the Economics of Android in an earlier post, and since then he's updated his work with the latest data and is studying RIM and Microsoft's efforts in the space as well.","2012-07-19",[2385,1498,1497],"/shuey/2012-07/img/kevin.jpg","content:shuey:2012-07:reset-button.md",{"user":2367,"name":2368},{"_path":2436,"title":2437,"description":2438,"publishDate":2439,"tags":2440,"image":2442,"_id":2443,"author":2444},"/tfarrel/2012-07","Looking at Steganography","With the help of one of my favorite news aggregators, I discovered this article on using JavaScript and the canvas element to hide information inside images. I've long been fascinated by steganography and this article and demonstration makes it even more accessible. If you can't be bothered to read the article, it describes a method of using the HTML5 File API and the canvas element to embed a message in images.","2012-07-24",[2441],"steganography","/tfarrel/2012-07/img/white.png","content:tfarrel:2012-07:index.md",{"user":2445,"name":2446},"tfarrel","Troy Farrel",1784782372012]