 So I've been working on this project for a while. It's not live yet. And when I heard about WordCamp Nordic, I was like, this is, I thought this is interesting. This is an unusually interesting project for me. And it occurred to me immediately that it'd be cool to come and talk about this. So thanks for having me here. I've been doing software for a long time, but I want to get into the context of this particular exercise, which is for a Finnish company called Finlasen. Finns will know this company. Many Nordics will probably be aware of this. Coming up to 200 years old, James Finlasen was a Quaker from Scotland who came to Finland and basically effectively brought the Industrial Revolution to Finland. If you can go to Tampere, you can see the old factories and buildings that he built at the time. They like movie theaters and museums and things like that. And Finlasen makes textile products. Their new stuff is coming out now. They have a lot of Moomin character-based things in the licensed Tom of Finland. The purpose of mentioning this, of course, is for general context, but also that they sell internationally. Japanese love Moomin products. And so when Finlasen licenses the Moomin characters, then they sell pretty well in Japan and elsewhere. They have some many thousands of products in total. Historically, they're not necessarily on sale anymore, as well as the current selection of products that you can find from their online store or in their physical stores. And they use this system called Perfion. It's a Danish company. There are others. This is a good one. I'm not specifically experienced in this product information management systems. For those that don't know what this is or what it means, if you imagine that you have products that you sell, physical products, like a bathrobe, three different colors, three different sizes, and you have towels in many colors and bedsheets and things, you need a way to manage all of that information. And I have seen this done using, for example, Google Sheets. Turns out Google Sheets has a two million sell upper limit. You hit that and it's annoying. So, after a certain point, you need a system to manage the data properly, including things like internationalization and translations. When you have a product named in three languages, you may have product images that are language specific. If you have a picture of a bathrobe, well, it's probably the same. This more applies to things like marketing images where it'll contain some text. But it can apply to product information. You can have a picture of a product that is tied to a language just like the textual description or name of the product might be tied to a particular language. And so Perfion is the product information management system that is being used and where all the information is pulled out from and where it is managed internally. The quotes, that's just, this is straight from their website. It wasn't appropriate to pull up an actual screenshot from their live system. Other parts of the context where we work, there are currently the consumer stores, finlayson.fi, finlayson.se, and international store at finlaysonshop.com, run on Shopify. And their ERP, which manages all inventories, prices, orders, customer information, is Microsoft Dynamics Nav. This just for background. It's a whole separate interesting story to discuss integration to these systems as well. But in this context, what's missing from finlayson and what we started to think about, so the problem that we had to solve was we need an online store for corporate customers. The absolute volumes of this are quite significant in addition to the consumer sales in online stores and in brick and mortar stores. There are visitors here and go to downtown Helsinki. There's a cool flagship store on Esplanade. And these customers, again, get back to the language thing. Of course Finland is important. You can go to Esplanade and there's the Moomin shop. You go in there, the finlayson Moomin themed products. Sweden, of course, is part of the EU, but Sweden has a bit of a special place here. The rest of the EU, Sweden, for example, does not work in Euro currency. We also use WPL multi-currency. It's not a topic for today, but was part of this problem overall. And the customization requirements are very different. In this case of corporate customers than for B2C stores. They come from different places. There are different customer groups. The selection of products out of the entire product set that finlayson has and produces in sales at any moment does vary based on country, based on like weird things I don't even know about. Brand license restrictions, for example. Finlayson uses Tomo Finland, Moomin. There's been some WWF work done previously, et cetera. And there are all kinds of like strange rules that apply to these and these have to be considered. And of course, specifically the language issue is important that for Finns, for the Finnish corporate customers, it's extremely important that they can do their business in Finnish. It's not, I mean, yeah, Finland's always no English, but it's important in a B2B relationship that the customers can work in the native language. They don't like Sweden. Then the rest of the world, they just get English. So, yeah, draw the line somewhere. And so, given this situation, we needed to decide on what we're gonna do about this. Previously, before I was involved and before this project got going on, Magento as a platform choice was considered and was not chosen. I don't have much more to say about that. Although I do want to point out that no platform has built-in multilingual support in its core, which I'm looking at all the people now that work on WordPress and WooCommerce and all the Magento developers, and that would be great. Because as a general comment, it's kind of a problem. Multilingual support is always overlaid in some way, maybe it's done well, maybe it's not not so well. But there's no obviously good choice from a platform or a technology perspective. And so, the end result was this goldilocks are too cold, too hot, just right was the WordPress as a technology basis and specifically WooCommerce with the multilingual features enabled on top. You get a basic store. We can do all the customizations we need for shipping methods and special payment methods and credit limit checking and whatnot. And we can do the multilingual thing. We evaluated Shopify and Shopify has a basic restriction that they're one language at a time. You can get like a multilingual overlay. It's doable, there's plugins, we kind of looked at them, but it seems more of a hack than WPML. I think WPML shirts, I think is the green one multilingual or I've seen some jumpers which say multilingual. So I'm wondering if there's their staff here. If there is, let me know and we can talk. So what we ended up with was this. We set up WooCommerce. We use the WooCommerce multilingual plugin and then the WPML basic translation core. And well, just out of curiosity, I mentioned some others that we use, not that it's important in this context. And the DevOps, the previous presenter. Interesting, thank you. We do most of those things. We use a Gitflow. We use WordMove to move the database back and forth. Interestingly, we have about 200,000 files in the uploads folder because we were a little bit lazy with like managing thumbnail creation is a bit of unnecessary thumbnail creation that we don't always need. But the product imagery overall is a couple of hundred gigabytes of images because we do also, for unrelated reasons, we also maintain the original full-size tiffs, which vary in size starting from 80 megabytes up to a gigabyte each. Plus then, generated thumbnails and special preview images. You can imagine a shower curtain is tall and narrow. We need to create a square image which has like white filled in on the sides. And so all the imagery gets multiplied crazily. Might have to do something about it at some point. But otherwise, yeah, you know, it was interesting to hear your presentation. There was some good pointers which I'll be picking up for our development. Anyway, to proceed to the multilingual thing, to get the product information from Perfion, from the product information management system into the store is on the one hand, it's a one-off operation when we start and we deploy the store. But that's not interesting. It happens once. Then on an ongoing basis, it must be updated constantly. The product information is actually updated daily within the company. Spelling mistakes may be corrected. Texts may be changed. And new products are created. Because in addition to having the current product selection in Perfion in the product information management system, also like upcoming products that are not on sale yet. So they're not public. You can't see them anywhere. But they're also managed and maintained and they are previewed in the system by staff. And so those things like, you know, there may be a photography day where product photos are taken and then those get updated, uploaded today. And then tomorrow, you know, somebody brings in all the Swedish translations. So we need an ongoing system for daily updates. And I was thinking also to add external scripts, you know, the integration component should, you know, where we put it. To add external scripts that we run with Cron that doesn't have to be programmed in PHP at all or what do we do? And considering that there's already an extensive list of customizations, you know, for the store to work in the first place, it seems inconsistent and extra complexity to have like something very different for this part. And so we wrote it as a plugin. But it's important to notice that we don't actually run the synchronization itself, you know, from the admins. That we don't press a sync button in the dashboard or having the automation there. Because then you're subject to the timeouts and usage restrictions, memory restrictions and timeouts because the sync can run for hours. So it makes no sense, like turn off all your timeouts and expand your memory use limits to like a gigabyte within that context. But you can run a sync from the admin console, from the dashboard, because sometimes we'll want to do a fast update. We'll modify the configuration parameters and say now we want just these five products, bring them in quickly. And it can be convenient to be able to trigger a sync from the dashboard. But primarily we run an external script using the command line interface and it runs on a cron task nightly and it has unlimited memory access. It can run for as long as it likes. Things like converting images. You need to load the image into memory in order to create a JPEG preview. We do our own JPEG previews, not always building on the WordPress built in. Thumbnail generation. And if you have a gigabyte sized image, you need to have enough memory allocated to the process to read in the gigabyte image and then it can create this small preview. So actually bringing in the data from the information management system. Perfion in this particular case offers two APIs. They're very similar. The first is the generic one, which historically they implemented first. It is generic. You get access to all the product information but it also provides no sort of online store related features. It doesn't help you very much. It's basically, have some examples, XML based and kind of inspired by SQL statements. And so you can do queries into the data and pull out that which you need. And they have an e-commerce oriented API which for example allows you to define channels. In Finlayson's case for example, we have this B2B channel which allows you to set certain rules on well what products will be pulled out, which languages will be included in the data, which product features, what product data specifically is brought out, which can be different from the consumer store for Finland or for the Swedish consumer store or for the international consumer store. There's actually seven Shopify stores that we run because there's Finland, Sweden, international. For each we have a test store where we can test things and then there's like a sandbox store where we play around with things. So we actually have eight different e-commerce channels defined each with their own different configuration so that we can get different controlled subsets of the product information into these different stores. In Perthion, you can organize your product information into a structure of product and variation, like you know you have your bathrobe and it's in three colors and three sizes but it's kind of the same bathrobe just in various variations. You can build that straight into the data and then you kind of don't need this but often that's not the case because the data originates from sales and the design people and the procurements and they don't organize the data in the way that the online store needs. So using the e-commerce API you kind of overlay that structure on top. And I wanted to specifically get into some of this technical stuff because these are the things that I found most specifically interesting that I wanted to share with you guys here today. The generic API is XML based. It is loosely oriented around SQL. And so in this example we're saying give me Finnish, English and Swedish contents. It may or may not exist and so one problem that we face is sometimes if they forget to put in like as the Swedish text, like well what do we do now? And there's nothing really you can do because if the Swedish text is missing and you need to publish this information to the Swedish store like you can't generate it here. You can flag it and stuff like that. In our case we default to Finnish. It's not great but you got to have something rather than nothing. So for Finnish is always our default in the case of missing data. We ask for these languages. We say feature ID and asterisk and say well give me everything just for this demo. I'm saying give me everything. We don't really do this normally because there's about 600 features defined. You get a lot of stuff. And I'm saying in this example just give me this one product. In our daily synchronization we don't say give me one product we say give me this defined subset of everything and we'll get typically about 1500 products in one run. We ask for three languages and so in the response, the first part of the response is metadata on the product. What is the information about the features that we're gonna get. And so I highlighted, it's not actually a great example but you can see each of them repeated three times because there's English, Finnish, Swedish. The ID is the same, this 1752. It's the same feature, marketing text. But it's in three languages and you don't get content here yet but this feature is called product type in English. And totally in Finnish and product type in Swedish. And in this particular example there's actually 2,000 lines of stuff because we have about 600 features features in three languages and so it all multiplies out crazily. Next part of the response is the actual product information. You can see as a product internal ID it shows in the first line the value says it's the SKU which is not localized, it's just once. It doesn't have a different product code in English and Swedish and Finnish it's always the same. There's a bar code somewhere. For example the designer year you see it halfway through. It's just once. So that's not in three languages. That's not a localizable feature. It's just a one language feature. It's a number. And so it comes through once. Bar code once, designer year once. But for example product title. We can see here in English it says thingami and bob bath towel. It's a mumikarakter. And I'm going to try and pronounce the Swedish one. I don't know Swedish one. And this is the generic API so there's no structuring of product and variation and what are the parameters on which the variations vary like size and color. But this is used in certain contexts and especially for debugging this can be great. The similar query using the e-commerce API is more oriented now towards an actual web store. We can say, I'll get products. We say what channel? So which store are we asking for? Give us the B2B configuration and that will give us certain values. It says include mappings is asterisk. We will get those mappings that are defined for the B2B store. Mappings means what feature data we get. What product information is actually given out of the 600 features total that we have for each product we want some for this store. And then we say here's the product code. Again for this example it's just a single code that I'm asking for. Normally we'll say give us 1500 at a time. We actually batch it into about 50 or 100 at a time. We don't actually pull out 1500. The system times out if you try. And then the result again is organized more in a more structured way. This product has fields and this is on the product level. So again to take the example of a bathrobe which has three colors and three sizes each that creates nine different variations each having a particular color and a particular size but then they all share much of the same product information in general. And so this is that general product information. We can see body HTML specifically oriented to the web store but here's how the product description the content for the product description. So in WooCommerce that becomes literally one to one that's the product description field. The title what is the name of the product et cetera. But again key for example is not in three languages because that value does not vary by language. And here you can accidentally see some custom stuff we have that this is sell only to countries. So there is some license restriction saying that FinLation is not permitted to sell these products to certain countries. I have no idea why like I don't know. I don't know more about that but it was a requirement. And so that's part of the product information. These products may not be sold to the countries and so if a customer of the B2B web store logs in we know who they are, we know what company they're associated with, they log in as an individual but they're associated with a certain business customer who is officially located as a Finnish customer or Chilean customer or from Thailand or Japan and then based on that we do filter. Not multilingual specific but because it shows up here. We also get information on so for this product what are the ways in which the variations vary. I don't know why the size came twice. A weird bug I noticed it just this morning. But here we're being told this product has variations and they will vary based on size and color. Somebody who does cars, it'll vary on engine size and if you do screws you'll vary on thread counts and things right but for textiles it's typically always color and size. We get this information and again in three languages so that when we show the information on the web store we can use the right language to say what we're talking about. Interestingly the Swedish translation seems to be missing for color and so it defaults to the technical name, internal name. Somebody has to fix that soon. Then the variants have information for example the thread count, ironing instructions they may vary like you have a t-shirt with three colors the black has special washing instructions but the others have different washing instructions so in addition to varying by color the variations may have different information. Images, again images can be localized you can have an English image and a Finnish image and a Swedish image in this particular case we don't really have that very much Finlayson they're always the same but this multi-lingual feature of Perfion applies to all features including images and if there were for example different Finnish, Swedish and English product images then they would be represented as multiple image elements here. On the first one you can see these bytes the actual base 64 encoded content comes through here we made that choice it's just technically slightly convenient the JPEG images are not very big so it's kind of okay for them to come through directly it makes the response quite large but it's convenient but then the main images which I think here you can see there's the tiff image.tif we're like if you want this image you can get it from this URL we don't base encode those into the response and then we say this one this particular product is its color is dark blue and its size is this thing we localize the size because mostly it's always the same but by localizing the size we enable using commas or full stops periods as the decimal which is kind of neat and when you have like one size is a size we can say that in three languages if it were just a centimeter number a whole number we wouldn't need to localize the size but we do localize the actual size information as well alright so this is the information that comes out of the product system now we need to put it into the store and I was wondering people may or may not be familiar with this already but I had to put this in that what works as an extension of WordPress is that a main product like bathrobe is a custom post type and there's some taxonomy terms which identify what kind of product it is it can be simple grouped, variable and there's a fourth which I don't remember external or something but in our case it's always variable it's always like a bathrobe, three sizes, three colors or like a pillow in two sizes and then the variations again are a custom post type and most parents indicates where they belong and again there's more taxonomies to indicate like what is the size what is the color and we transfer information of the variations into the appropriate WooCommerce taxonomies so that they are displayed properly in the right languages but this is just forward language whatever the default WordPress WooCommerce installation is in our case the WooCommerce multilingual plugin which builds upon the WPML things and it duplicates everything and when I first ran across this a few years back when I started working on this it was ridiculous like why don't we build them in but the other option is also not good if you start trying to bake in multiple languages into the same post type but first of all WordPress doesn't really allow that you can't really do that it's just the way you have to do it and it's fine but you do get a lot of entries in your tables everything is triplicated all attachments are triplicated because we have three languages but it works each of the on each level the product level bathroom they have a translation ID which ties them together so we know which is the translation of which and one is always the source language it doesn't make a big difference to the end usually they don't see anything but technically we know which was the original and then these are translations of that and the same applies to all variations so you get laboratories which is fine we only have about for example in one particular instance of a store we have about 1200 products but like our post ID count is already like 200,000 just from our development of products in, products out, develop, update and then the artistic counter keeps going so you get into big numbers but it works so thank you to all the WPML contributors it's a good system and then finally some comments on actually creating the products this is where there was some challenges because WooCommerce has a good PHP a PHP function API for getting information so if you're writing a plugin like we do you can get information, you can load a product you can ask for the children, you can get the information but there's nothing for creating programmatically there's some extensions to the WP REST API so if you're calling the REST API externally you can say create a product, create a variation but we decided not to do that it wasn't a good decision, I'm quite sure but we wanted to do the coding in the plugin same thing for the multilingual stuff WPML itself plus WCML which is the WooCommerce multilingual also there's no set of PHP functions for creating stuff so everything that I know now has been basically reverse engineered because there's also no documentation for this the only thing I've not done is I've not actually been specifically in contact with the WPML or WCML teams maybe I should now but looking online for information I would ask about this and then the moderators on the WPML WCML forms like we don't have that so I've been digging around in the database now I know how it works because I've reverse engineered the whole thing if I want to be rich and famous now I need to write like a library which does this it would be awesome I would pay a lot of money and I would charge my customers that money just someone who writes a code library for writing creating products in WooCommerce and doing it multilingual that would be really valuable because we spend a lot of time having to do it ourselves by reverse engineering a final comment on the synchronization process that we run it's well to be straightforward but it was not obvious like doing it it's obvious now that I can write it here it took us a while to kind of figure out what makes sense we find first what other products we want in this particular store it's always a subset of everything it's never everything it's always some things for example upcoming products that are not public yet of course we don't want those historical products not being produced anymore no point we do a fast prefetch because performance can be a problem talking to the Perthian API sometimes you have to do everything within about 60 seconds or it complains so we ask for give us all the IDs based on that and the SKU is the product codes then we do a simple comparison we say well what products do we know in our store now and then what are the products that we're supposed to have and we just compare them there's new products that we don't know about okay we need to create these products and then we have products in the store which are not included in this query response so we've got to delete these products because they're going away and then the rest we update for boring reasons we can't use last modified timestamps which means that we always update everything because we don't actually know what has changed we want to know why come and ask afterwards which is why the database the process runs for about 3 to 6 hours we do it nightly and it's fine and we might need to make it better later but it's okay for now and using the awesomeness of the WP command line interface we wrote this as a plugin we get to use all the WordPress and WCML and WPML features and utility functions but then we use like a gigabyte of memory and it runs for 5 hours we can run it outside I'm only recently familiar with WP CLI so I'm enthusiastic about it because it's very cool we had trouble with timeouts in the dashboard previously but that's it from my side thank you hold on for a second you have time for questions first of all thank you but I'm still kind of what the hell is going on at least I know that it's at least I know that it's really hard to have moldling or online store I do get that and I kind of appreciate that you was kind of telling the points that you had in developing that kind of sites so now we have time for questions hello I have two questions actually the first one is how did you manage with that amount of uploads how did you manage to work with it efficiently like going from local to a staging to a production because I mean obviously you take the files from production and down but if you have hundreds of gigs that's a nightmare isn't it how did you manage that we have 235,000 files 233 gigabytes and we use word move which is basically our sync to move it around and it's really painful having said that just a sec the delta from day to day is not huge so once upon a time I ran word move I synced everything down to this laptop right here it was maxed out years ago and I had to clean up a huge amount of space which is very annoying so I had to make 250 gigabytes of space and then I synced everything down and it ran for about a week and then I had everything from Perfium and it took another week to push it up to our staging environments and then it took another week to go to production so I spent about three weeks and I would go into work and come home and my laptop was always open in my car and it was ridiculous but now that it's done the delta from day to day is not bad but our sync does struggle hugely it fails mostly I only get successful our sync about 175 times that I run it it's a problem it's not a big problem that the consumer is like oh my goodness this doesn't work or my customer is happy but yeah it's a problem for us sounds serious the end result is fine so it's worth it but yeah this is annoying my other question is how come you chose WPML as a multilingual and the background is that I myself has actually been sued for and lost in court for using WPML we helped a client who had WPML and there were bugs in WPML and if anyone else has used WPML there are lots of them in WPML because the code is a bit wonky as you might have noted and well how is it working out for you because like the judge said hey Jimmy you know if you're an expert in WordPress you should probably know that you shouldn't use this and you should have better what was the trouble you had with it what can I say the main problem was that the client did not understand that you know in open source no one is really responsible for the end product I mean you sell your time to help them customize but in court the judge did not agree it was the judge considered a product and we should know better probably so now we use a multilingual press instead and I would say that it is a much better solution and it has never caused us any issues good to know I'll use that next time we use WPML because honestly a good friend recommended it and said this is great it was fine with regard to open source components and technical issues and bugs I have always made it clear to all my customers like ever that I'm going to use open source if you don't use open source here's the alternative cost I'm going to recode this whole thing it is a good idea to use open source but hey if there are bugs I'm not responsible and I put that into the contract and I make sure that the customer understands there's not just fine print that they don't get make it completely clear so far my customers I believe have understood this and it's baked into the contract explicitly if there is a defect in the open source components I am not responsible but I do contractually obligate myself to do my best to fix it in the actual component itself that would be great cool I get to contribute or to develop a workaround but I will charge by the hour for that and if it doesn't work I'm like sorry I always cover my back it has not been a problem but I hope to be prepared for this case we had a lot of problems with the checkout and you know small things that didn't work and broke it was bad I don't look forward to seeing those myself hopefully I won't see them next guys there was a couple of hands at least I think you were first and then here and then here thank you it was very interesting regarding the images we have a we have a client where we import daily or many times they used cars that they sell and then it of course results in heavy really much images on the on the production server so what we do on our dev environment is that we have in our htaccess file so that if it doesn't find the image locally it just loads that image from the live site instead so that I don't have to ever take the uploads to my local we have one paper with my colleague we have designed and planned to implement once it becomes too painful we'll probably move the whole uploads into an Amazon S3 bucket and link to it from everywhere it causes different kinds of problems then because all environments share it and is it in sync you're kind of exchanging one problem for a different problem right now we struggle with the word move in sync thing because even though it's problematic when the r sync does go through we're cleanly separated in our environments and we don't have weird side effects I just need to retry all the time every few days I get a full sync and then we're good and then I wanted to ask do you run the loading the import script on the same server as you hosted or in a different server you run on the same server as you else wise when and if we need to we'll run it separately and then have you ever encountered where you need to have different product images per country instead of per language no but the solution we have for filtering products based on customer group probably we would be able to adapt that but I think that the stuff we've done probably would be straightforwardly expandable to do that we've done something very similar thank you so first of all thank you for a good talk and I feel sorry for you having to work on SOPE I feel you SOPE client is I'm probably just having my own opinions on it I'm not going to do them now secondly we've come to like performance and issues regarding that I'm thinking it's a big site and how did you solve them if you could give an example the biggest performance problem we had was a bug in WooCommerce which is going to be fixed soon I don't remember the numbers and the codes but it's not actually in a release yet where a stupid number of cron jobs are created version transients I haven't been interested enough to dig in any deeper I can point you to it and that completely kills the site because then there's like 5000 entries in wp options for cron jobs and I just when and if that happens sometimes happens when lots of products are synced the day to day delta coming from the product information management system is not huge but sometimes it's big like a whole collection is released and we get a lot and that's just waiting for that bug to be fixed WooCommerce update and right now I just kill at PM and I just delete that totally brute force although today I learned actually one of the presentations had a couple of lines of codes maybe that would solve my problem otherwise performance no it's not really a problem we have a medium sized server it's just one we don't run a farm or anything absolute number of customers is not huge the volume of business is pretty big because it's consumers it's corporate customers coming in to make large like for a hotel they'll buy like a thousand towels at a time for example we have a medium sized server with no special special performance oriented configurations so far thank you now it's this guy's turn so actually yes hi in the near future we're building a kind of similar setup with little less products a little less complexity I'm gonna use polyline role for that and I can tell the results later but my question is really about time estimates like how long did it take for you to set up the plugin that synchronizes things and the WooCommerce settings and such because I don't want to give two two positive estimates in this context the thing that has taken time is simply writing the code that starting from soap clients you make a request you formulate the query XML make the request, you get the response I was almost gonna draw a picture of this you get the XML response I have domain classes in PHP to represent exactly that XML no transformations yet into WooCommerce products I just take the XML and I represent that in PHP just so that I have that without soap client I don't actually want to talk to soap client I want PHP class representations but one to one of that XML data from there I will then make a transformation into my own domain classes which do not follow this model it works and I need to know my code so I have a bunch of classes which have, for example, products but it is a multilingual product when I make that super awesome library which will make me rich and famous it will be based on this where I have a single class which represents an arbitrarily multilingual product and that is then able to create this stuff into the database and I kind of mix doing stuff directly into the database mostly I try to be a good citizen and I use WP functions sometimes I'm like I kind of dive straight into the database but then you skip filters and things doing this overall was about two months of work two to three months including the original development was two and then further work is another one so the total investment in effort has been approximately three months to create this synchronization that I just got. Thank you. I'm going to block you a little bit so you can ask privately because we don't have time for many questions. I can hang around for a bit. On the back I think was one head up I think we're going to need to have that as a last question you can ask also privately afterwards so we can have a break little break between the last speeches but you can definitely ask after this so last question goes from here. Hello, great talk. There were questions about performance but have you around with Black Friday's performance and how to keep all the multilingual stock and stuff synced on tons of requests per second for all the multilinguals? No. This things like Black Friday Christmas sales Easter sales, summer sales don't apply to this particular store because it's corporate customers and we don't get load peaks like that. The absolute load of users on the system is pretty low. It's a small number of users like hundreds. Totally based on hundreds of people that's it but because the corporate customers they go to a hotel or a chain of stores in Finland there's a dozen of them around Finland and now we need more movement bath towels they don't actually know the numbers but a few hundred people logging into this system produce millions in sales so that kind of performance issue we don't have with this we probably will never have that problem. Thank you again. Now we kind of have to stop so we're going to have a break we'll be back in about 10 minutes with our last round of speaker. One more applause for Alan. Thank you.