[{"data":1,"prerenderedAt":194},["ShallowReactive",2],{"work:\u002Fwork\u002Fvialuxury":3,"work:\u002Fwork\u002Fvialuxury:surround":181,"page:work:cta":187},{"id":4,"title":5,"body":6,"client":92,"compare":93,"country":101,"description":85,"extension":102,"glance":103,"industry":107,"logo":108,"meta":113,"navigation":114,"order":115,"path":116,"people":117,"peopleNote":141,"period":142,"published":114,"quote":143,"seo":144,"service":145,"stack":146,"stem":153,"summary":154,"team":155,"timeline":156,"__hash__":180},"work\u002Fwork\u002Fvialuxury.md","Moving a live booking platform from Ruby to .NET without stopping it",{"type":7,"value":8,"toc":84},"minimark",[9,14,18,21,25,28,31,34,38,45,51,57,63,67,74],[10,11,13],"h2",{"id":12},"the-problem","The problem",[15,16,17],"p",{},"Vialuxury sells hotel stays with the extras included: dinners, wellness, experiences. Their platform was built in Ruby on Rails, and it worked. It was quick to change and the team knew it well.",[15,19,20],{},"Two things had become a problem. It had become expensive, and at busy times it fell behind on hotel availability updates, so the prices on the site could lag behind what hotels had released. Rewriting it in one go was not an option. Bookings come in every hour of the day, and years of business rules lived in the code, some of them in files rather than the database.",[10,22,24],{"id":23},"what-we-did","What we did",[15,26,27],{},"We built a new .NET core next to the Ruby one and moved the platform over one area at a time. Both systems run against the same Postgres database. Rails still owns the schema and .NET maps onto the existing tables, so switching an area over is a routing change that can be undone.",[15,29,30],{},"We started with accounts and passwordless sign-in, then finance reporting and invoicing, hotel availability, cancellations and refunds, and the sync of all content from the CMS. Checkout and payments go last.",[15,32,33],{},"Nothing took over until it matched Ruby on real data. A parity harness runs the Ruby and .NET versions side by side against the same CMS content and compares every row they write. Checkout runs in shadow mode: every live order is also calculated by .NET and compared with what Ruby charged.",[10,35,37],{"id":36},"what-was-hard","What was hard",[15,39,40,44],{},[41,42,43],"strong",{},"Rules outside the database."," Email templates, discount rules and a partner list lived in Ruby files and constants. They had to be found by reading code, not data, and one list changed on the Ruby side after we had ported it.",[15,46,47,50],{},[41,48,49],{},"A type system that let things slide."," Hotels and packages both have a status, but 0 means draft for a hotel and published for a package. Ruby read some whole numbers as decimals and turned missing amounts into zero without complaint. The parity runs caught these one at a time, and a few differences turned out to be Ruby bugs that the .NET version now fixes.",[15,52,53,56],{},[41,54,55],{},"Two systems, one database."," Ruby's background jobs still run against the same tables. An old nightly job could overwrite a field the .NET side had just set, and removing a Ruby job could quietly stop something that depended on it. Every change started with finding who else writes to that table.",[15,58,59,62],{},[41,60,61],{},"A rollback."," The first switch of cancellations to .NET was undone the same day: under production load, background jobs on one server held locks the others were waiting for. It went live again four days later.",[10,64,66],{"id":65},"what-changed","What changed",[68,69,71],"case-highlight",{"label":70},"At peak times",[15,72,73],{},"When many hotels update at once, availability no longer falls behind. The slowest updates now land in seconds, where on Ruby they could take minutes. Customers see the prices hotels have released, even at the busiest moments.",[75,76,77,81],"ul",{},[78,79,80],"li",{},"Hiring is easier. There are more .NET developers to choose from than Ruby ones.",[78,82,83],{},"When Ruby is switched off in October 2026, Vialuxury runs one stack instead of two. Until then it stays up as a fallback, which the business asked for.",{"title":85,"searchDepth":86,"depth":86,"links":87},"",2,[88,89,90,91],{"id":12,"depth":86,"text":13},{"id":23,"depth":86,"text":24},{"id":36,"depth":86,"text":37},{"id":65,"depth":86,"text":66},"Vialuxury",{"before":94,"after":95,"beforeAlt":96,"afterAlt":97,"width":98,"height":99,"caption":100},"\u002Fwork\u002Fvialuxury-home-before.webp","\u002Fwork\u002Fvialuxury-home-after.webp","Vialuxury home page before the redesign","Vialuxury home page after the redesign",1288,936,"The home page before and after the redesign Ilhan built. The new version is live as an A\u002FB test.","Netherlands","md",{"problem":104,"approach":105,"now":106},"A Ruby platform that worked, but had become expensive and fell behind on hotel availability at busy times.","Built a .NET core next to it on the same database and moved one area at a time, each proven against Ruby first.","Accounts, finance, availability, cancellations and content run on .NET. Checkout runs in shadow mode. Ruby is switched off in October 2026.","Luxury travel",{"name":92,"src":109,"srcDark":110,"height":111,"ratio":112},"\u002Flogos\u002Fvialuxury.svg","\u002Flogos\u002Fvialuxury-light.svg",72,1.2633,{},true,1,"\u002Fwork\u002Fvialuxury",[118,123,128,133],{"name":119,"role":120,"image":121,"link":122},"Aleksa Kuzman","Architecture of the .NET core, content sync, search indexing, redirects","\u002Fteam\u002Faleksa.webp","https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Faleksa-kuzman-653998190\u002F",{"name":124,"role":125,"image":126,"link":127},"Boris Radevic","Accounts, finance, availability, cancellations, checkout and payments","\u002Fteam\u002Fboris.webp","https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fboris-radevic-46337b2ba\u002F",{"name":129,"role":130,"image":131,"link":132},"Ilija Racic","Tracing, logging and alerting; content sync fixes","\u002Fteam\u002Filija-2.webp","https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Filija-racic\u002F",{"name":134,"role":135,"image":136,"link":137,"website":138},"Ilhan Kalač","The redesigned front end: search, offer pages, checkout, account and home","\u002Fteam\u002Filhan.webp","https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Filhankalac\u002F",{"label":139,"to":140},"ilhan.io","https:\u002F\u002Filhan.io\u002F","Search, the product pages and the home page API were built by another team working on the same platform.","February to August 2026",null,{"title":5,"description":85},"Modernisation and migration",[147,148,149,150,151,152],".NET","PostgreSQL","Wolverine","Elasticsearch","Redis","Nuxt","work\u002Fvialuxury","A hotel booking platform moved from Ruby to .NET one area at a time, with both systems running on the same database. Each piece took over only after it matched the old one on real data.","4 engineers",[157,160,163,166,169,172,175,177],{"date":158,"text":159},"Feb 2026","New .NET core running next to Ruby on the same database",{"date":161,"text":162},"Mar 2026","Accounts and passwordless sign-in",{"date":164,"text":165},"Apr–May 2026","Finance: booking and payout overviews, invoicing",{"date":167,"text":168},"Jun–Jul 2026","Hotel availability processing",{"date":170,"text":171},"Jul 2026","Cancellations and refunds, after one rollback",{"date":173,"text":174},"Aug 2026","Content sync from the CMS, and redirects",{"date":173,"text":176},"Checkout, pricing and price checks running in shadow mode",{"date":178,"text":179,"upcoming":114},"Oct 2026","Ruby switched off (scheduled)","AdZz1kmRPzx6Q3hNedaUJebJY1gEOINN3639m-pOIUA",[143,182],{"title":183,"path":184,"stem":185,"client":186,"children":-1},"One home for test data from Corning's outside manufacturers","\u002Fwork\u002Fcorning","work\u002Fcorning","Corning",{"cta":188},{"title":189,"note":190,"button":191},"Have something like this? Tell us about it.","The first call is free, takes 30 minutes and commits you to nothing.",{"label":192,"to":193},"Book a call","\u002Fcontact",1793174665534]