Laravel Live Japan – Live from Tachikawa Stage Garden
Chapters6
Opening remarks introduce the event, attendees from around the world, and the goal of bridging the Japanese PHP and global Laravel communities.
A high-energy kickoff for Laravel Live Japan featuring global speakers, hands-on AI demos, and practical Laravel tooling tips—plus surprising showcases like music with PHP and real-time analytics with ClickHouse.
Summary
Laravel Live Japan kicks off with Hyota Hamasaki framing a mission: to bridge Japan’s strong PHP scene with the global Laravel community. MC Daniel Colborn keeps the vibe warm and bilingual as speakers jump into bold topics. Nuno Maduro shares a practical philosophy on “strict engineering” for Laravel, highlighting features like “should be strict,” lazy loading guards, and a defensive posture for destructive commands, then riffs on PHPStan and TypeScript as AI copilots for code quality. The talks then bounce between deep technical demos and creative showcases: Nuno’s live-coding style, a practical night of testing pipelines with Laravel Pint and type coverage, and a Claude-assisted live feature demo. Jess Archer dives into ClickHouse via Laravel Nightwatch to demonstrate how analytics and real-time queries compare across MySQL, PostgreSQL, and ClickHouse, with vivid performance contrasts. Marcel from Germany shreds the idea of programming with sound, showing music generation in PHP using ReactPHP and SuperCollider, illustrating how far real-time PHP can bend. The day is peppered with rapid-fire lightning talks on API docs with Scribe, mocks vs. stubs in PHP Unit, and pragmatic takes on Laravel’s architectural discipline (the Lar Way). The program closes with a keynote from Taylor Otwell and a look at Laravel Cloud’s new Tokyo region, autoscaling, and managed queues, underscoring Laravel’s push toward AI-ready, scalable production in 2026. Throughout, attendees exchange languages, experiment with translation tools, and engage in lunch-matching and afterparties to keep the community momentum high.
Key Takeaways
- Defensive defaults in Laravel (should be strict, prevent lazy loading, and prohibitions on destructive commands) dramatically improve production safety and AI-assisted coding feedback.
- PHPStan and TypeScript act as critical quality copilots for AI-driven development, catching issues across PHP and front-end code at scale.
- The Laravel testing pipeline (lint, type coverage, parallel unit tests, and AI-guided scaffolding) is essential to keep AI-generated code production-ready.
- ClickHouse can dramatically outperform MySQL/PostgreSQL for large-scale analytics; including data partitioning, materialized views, and TTL-based retention are key design patterns.
- Laravel Boost and the Laravel AI SDK enable practical AI workflows (agents, tools, streaming prompts, and multi-provider fallbacks) that integrate tightly with Laravel projects.
- Laravel Cloud’s Tokyo region, autoscaling, and managed queues demonstrate how to operate AI/real-time workloads at scale with minimal ops friction and observability.
- Creative demos (music with PHP, real-time analytics, and AI-driven feature generation) showcase how PHP can extend beyond traditional web apps and into real-time, expressive domains.
Who Is This For?
Essential viewing for Laravel developers exploring AI-assisted development, site reliability, and advanced analytics. It’s especially valuable for teams considering deploying Laravel Cloud, integrating AI SDKs, or experimenting with real-time, data-heavy features.
Notable Quotes
"So today is the day to start turning that wall into a bridge."
—Hyota Hamasaki frames the conference’s mission to connect Japan’s PHP community with the global Laravel ecosystem.
"Agent coding is not vibe coding."
—Nuno Maduro emphasizes disciplined, explicit design when using AI to generate code.
"It's literally the equivalent of TypeScript for PHP."
—Nuno Maduro extols PHPStan as a must-know tool for PHP development and type safety.
"We are going to make music with PHP today."
—Marcel demonstrates PHP-based real-time audio generation to illustrate PHP’s expressive capabilities.
"AI can help you translate requirements into working software, but the bottleneck is shifting upstream to specification."
—Taylor Otwell frames Laravel’s AI-forward trajectory and the importance of clear specs in AI-driven development.
Questions This Video Answers
- How can Laravel Boost speed up AI-driven coding in a Laravel project?
- What makes ClickHouse a strong choice for Nightwatch-style analytics in Laravel?
- What is the Lar Way and how does it guide architectures in Laravel with AI?
- How do I start using the Laravel AI SDK and what features support streaming and agents?
- What benefits does Laravel Cloud offer for auto-scaling queues and regions like Tokyo?
Laravel Live JapanLaravel BoostLaravel AI SDKPHPStanTypeScriptClickHouseLaravel NightwatchLaravel CloudAuto-scalingLaravel Herd/Octane
Full Transcript
Heat. Heat. Are you crazy? I just want to make you mine. M I just want to make you mime. I just want to make you I just I just want to make you I just want to make you I just want to make you make you I just want to make you I want to make you I make you Make you I want to make you I make you. I swear to you. I just want to make you. I just want to make you. I just want to make you I just want to make you I just I just want to make you I just want to make you make you I just want to make make you Heat.
Heat. N. I should make you I woo. Hey, hey, hey. Hey, Heat. Hey. Hey. hey, hey. Woo! Oh, Woo. Hey. Hey. Hey. home. hey, hey. into the sunlight. Wow. Can't stay. love your game. Mine. M. I just want to make you mine. I just I make you you make you I I just want to make you I just want to make you I make you into the sun. Yes, am. make you I just make you I make you I I want to make you make you I just want to make you I Just I make you I make you make you Good morning.
Yeah. Thank you so much for joining us for the very first Laravel Live Japan. Welcome. Um, I need to get my clickers. Um, cool. Live translation is working. Okay. Um, again, welcome to Laravel Live Japan. Um this is the very first Laravel conference in Japan and my name is Hyota Hamasaki. I'm a software engineer at Laravel building the observability platforms for Laravel applications and I am the organizer of Laravel Lab Japan. And before we begin I want to see who is in this room. Raise your hand if you're joining us from Japan. Uh, sorry. Uh, raise your hand if you're joining outside Japan but Apac Asia Pacific.
Yeah, thank you for joining us. And Europe. Yeah, a lot. America, South America, North America. Yeah, cool. Africa. And who are students? I think we have a lot of students today. Yeah. Thanks for joining us. Um, yeah, look around. Today we have around 600 artisans from across 42 countries in Tokyo. So, we have different languages, different countries, different cultures, but today we are one community. Yeah, thank you. Um, Japan has a passionate and PHP uh huge and passionate PHP community. There are PHP conferences almost every month in different cities across Japan. Just two weeks ago, there was PHP conference Kagawa and next week PHP conference Hokkaido is happening.
It's like crazy. Um have you heard of any countries like that? Um so the community is very strong, the quality is high, the you know energy is incredible. But at the same time I've al always felt that there was an invisible wall between the Japanese PHP community and the global Laravel community. Part of it is language, part of it is distance, part of it is culture, but maybe part of it is simply that we didn't have enough opportunities to meet each other. So today is the day to start turning that wall into a bridge. So this conference is very special and personal for me.
Uh just a little bit about my journey and I attended my first Laron in Chicago in 2018. For those who don't know Laron, it's the biggest Laravel conference in the world. In Chicago, I got to meet Taylor, the creator of Laravel, and many fellow artisans from around the world. and talking to people who were building the real things with Laravel, I felt so excited, so motivated and so inspired. And after that, I had this thought someday I want to speak on that stage. The next year I submitted a talk to Lacon EU. Honestly, I had no expectation that my talk would be chosen.
But somehow I was selected as a speaker and gave a talk in front of thousand people in Amsterdam and that was my first conference talk which was crazy and it was terrifying but that one single opportunity gave me the courage to keep sharing, keep connecting and keep challenging myself. Later I moved to Singapore and eventually joined Laravel, my dream job. And now we're here, Laravel Live Japan. So I'm deeply grateful for everything this community has given me. And that's why I wanted to bring back this experience to Japan. Not just the talks, not just the speakers, but I wanted to bring back the feeling that I had in Chicago.
the feeling that the global Laravel community is not far away. It's right in front of you and you can be part of it. Whether you're an experienced Lar developer just getting started, a front-end engineer, designer, founder, or just curious about the community, you are part of this community. And today and tomorrow, we have an incredible lineup of speakers. Learn from them, get inspired by them. But conferences are not just about watching the talks. It's more about connection, connecting with people. And this conference is not happening only on this stage. It's happening everywhere in this venue.
So talk to people around you. Say hello to someone you don't know. Ask what they're building. Share what you're working on. A single conversation at a conference can change your life. like like Laron US changed my life. Of course, one of the biggest barriers here is language. So, I built a small live translation app for this event. Not just this uh translation on the main screen, but something you can use to talk to someone who speaks different language. So, go to larlive.jptalk JPTt talk and you can start a conversation on your phone. And now you can invite someone to a conversation by scanning the QR code on on your screen and a new session starts someone when someone joins and press press the button when you speak and it will be translated in real time on someone else's uh device and stop the button when you are done and multiple people can join the same session And actually, I deployed it last night in my hotel room.
So, sorry if it's broken. It's not perfect, but I hope it helps. Yeah. And if you find a bug, just yell out to me directly. Um, Pac-Man rule. Do you know Pac-Man rule? Okay. Um so when people are chatting in a group if the circle is completely closed it's really hard to you know hard for someone to join the conversation. So the Pac-Man rule is very simple. Leave a small gap and like Pac-Man's mouth so other people can join the conversation and when someone new joins just make new space again. It's easy right? And this event wouldn't be possible without the support of Laravel uh sponsors, speakers, volunteers, staff, and each one of you here to be part of this moment.
Thank you very much, Antonia. And I also want to thank my beautiful wife. Uh she's my biggest sponsor and she's in the audience today. Okay. Um okay. Now I'm very excited to introduce our MC. Um he is based in the US but he spent many years in Japan and SP he's spoken at many lons around the world and he brings a lot of energy to the stage. So, please join me in welcome MC Daniel Colborn. Oh, clear. That's what I'm saying. Okay. Uh for the for the Gajene in the audience, uh uh what I just said was uh I'm Daniel Cobburn.
I'm going to be your MC for the uh for the conference. I'm super happy to be here. Uh, I grew up in Japan as a child from the ages of 3 to 17. Um, and so I have been in America for the last 15 years not speaking Japanese on a daily basis. Uh, so while I understand a lot of Japanese and can speak Japanese conversationally, uh, I'm going to do most of my MCing in English. So, uh, I appreciate your patience with my bilingual fumbling. Um, all right. I appear to not have slides. Okay. Well, oh, here.
Well, here's a good opportunity. Uh, one of the things I want to do while I'm here, uh, I know we have a bunch of foreigners, uh, and people who don't, uh, aren't always in Japan who've traveled here just for this event. Uh, and we're super happy that you're here. Thank you for making the journey. Um, we want to help teach you all a little bit of Japanese. So, we're just going to sprinkle in little Japanese vocab words for the foreigners uh throughout the program. So, obviously the first one that we should learn, I think you've already heard me say it and you've heard everyone else say it is, which means good morning.
So, for our foreigners, let's all learn. And then tomorrow when you come in and you meet people, you can say to everyone. Ready everyone? All right, great job. So now you know how to say good morning in Japanese or you were Japanese and you already knew in which case um all right, how are we doing? Okay. Uh, I need to make a few announcements about uh, wifi and restrooms, etc. So, I will get into the ones I can do without the slides. Uh, the restrooms are in the halls on the outside. So, uh, you can exit anywhere you want.
In the back here is the sponsor area. Um, so you want to go speak to all of these sponsors. While you're speaking to the sponsors, please keep the volume just down just a little bit because if everybody goes up there and talks to all of the sponsors at the same time that a speaker is up here speaking, we won't be able to hear the speaker. Um, so while you're up there speaking to the sponsors, if there are talks going on, please keep the volume low. Um, and uh there is water and tea, I believe, up there as well.
So if you need something to drink, water, tea, and also coffee I think up there as well. Do we have do we have our slides or no? I have no slides. All right. Um, what is next? What is next? Okay. So, uh, we definitely need to talk about Wi-Fi. Is everyone on the Wi-Fi? Have people discovered the Wi-Fi? Do you What's the Wi-Fi password? Laravel forever. Uh Wi-Fi SSID is Typesense. Our sponsor, Wi-Fi sponsor. The password is Laravel forever. Laravel for number for ever. All right. So the SSID once again is Typesense. Uh thank you to Typesense, our Wi-Fi sponsor.
And the password is Laravel, the number four ever. Aha. Thank you to the AV team. That's great. All right. Now, is my clicker Does it click? This is the Laravel logo. It's a very pretty logo. We love it. Okay. Um, so I uh grew up in Chiba. So I grew up uh in Makohari in Chiba, which is just across the line into Chiba by the Makohari Messi. Um, I grew up going to Chibarote Marines Games. Um, so I'm a Marines fan from the Bobby Valentine era. Um, I uh, so my parents lived in Makohhati. I grew up there.
Um, I went to school sort of deeper into Chiba, but every week I would come into Tokyo to hang out with friends in like Shibuya or in Harajuku or wherever and we would hang out in Tokyo and do stuff. Um, so I love Japan. I love the Laravel community. So I've been in the Laravel community since I want to say 201 15 or 16. Um I started using Laravel or 161 17 I forget but it it was like right around Laravel 4.2 no Toki um and so I got into Laravel then and started using it and I've been to uh many Laracons and been deeply involved in the Laravel community.
Uh I've spoken at uh all four Laracons in US, Europe, India and Australia. Um, and so I love the Laravel community. This has been my home for my career is the Laravel community. Uh, and so I was very excited when the opportunity came to come bring the Laravel community to Japan. Uh, I know that obviously you already have your own uh, community here, but bring the global Laravel community to Japan and sort of marry my home where I grew up to my my career home and my technology home. Marrying those two things is very exciting to me.
John, I'm just going to uh keep killing time until I get my slides back. Um, so we have speakers from all over the globe as well. um and many of whom I have known for quite some time uh who I've spoken with at uh many other conferences. Lots of them are hiding back there in the sponsor area. I see them. Um these are our friends. Um and so I'm really excited for you guys to all get to hear from them as well. Uh these are some of the some of the best uh thinkers in the Laravel community uh who've got lots of ideas and cool opinions and are great speakers.
Uh so I'm very excited to hear from them. Uh we've got uh who do we have? We have Jess Archer uh who works for Laravel on the uh on the Nightw Watch team who's going to be talking to us about ClickHouse. We've got Joe Tannen Bomb who works for Laravel on the open source team who's going to be talking to us about I assume Wayfinder um and and other open source things. Um, we've got uh James, we've got all sorts of folks. Marcel is here as well. Uh, I don't know if any of you use uh Laravel Herd, but that's an incredible piece of software that I use that Marcel built every day.
Um, so I'm really excited to uh have all of those folks out here as well as I'm super excited personally to get to hear from a lot of the Japanese PHP community uh and people who are already organizing uh Japanese PHP conferences here. So uh I'm super excited for that as well. Oh, let's talk about lunch. Lunch. So, we're not providing lunch. Sorry. this venue is not allowed to, you know, eat or drink. Do we talk about it? Yeah, we haven't talked about that. So, that's a good idea. We can't have food or drinks in the venue.
So, sorry. Um, however, you can have uh like bottles with lids. So, if you have a drink and it has a b it's in a bottle and the bottle has a lid, that's okay. Uh, if you have a drink and it's in a cup, that's not okay. So, y and during the lunch break, maybe just go out and have some lunch there. There's lots of places to have lunch. And if you bring your name badge, you know, some shops give you some discounts. So just, you know, don't forget to bring your name badge. Um, yeah.
So this air, this whole area out here that's part of this complex, many of the restaurants in there are offering discounts if you have your name badge. So yeah, bring it along. And if you don't have, you know, someone else to go lunch together, we have lunch matching during the lunch break. So if you want to join lunch matching just come on to the stage at the beginning of the lunch break and we're going to form a group of like three to four people and then yeah let you go lunch together basically. I think we're back or are we back?
Are we back? Okay. Have we covered everything? I think in addition to lunch matching um we also have uh an afterparty tonight after the uh after the event uh which was ticketed separately. So if you got um tickets to that, congratulations. I can't wait to see you there. If you didn't, I'm so sorry. Uh have have fun anyway. Um, and that is at a uh that's at a nearby venue. Um, which the address is on your uh ticket to the event, but I will also uh make another announcement about it at the end. Um, and that's sort of nearby.
It's a basketball venue. Um, so there it's like there will be food and drinks, but also if you want to play basketball, you can play basketball. So, uh, that's cool. uh when we had uh we had Laracon in Dallas a couple of years ago. Uh I know some of these these guys remember uh that some of us were forced to play basketball uh before Laracon. So Taylor and Tom and me and some famous YouTubers uh and James and others uh had to play basketball. Uh, and I was very bad at basketball. Even though I'm very tall, everyone looks at me and they think, "Oh, you probably play basketball." And the answer is, "I play basketball, but I play it very badly." Yes, sir.
We're ready. Okay. All right. So, uh, with all of that out of the way, uh, we weren't able to get slides up for most of the announcements, but I think you have mostly everything you need. Uh, so at this point, I'm going to just introduce our first speaker. So, uh, our first speaker coming all the way from Portugal, although you came straight from Brazil this time, right? So, he was in Brazil, but he's from Portugal. Uh, he is the president of Nuno Nation. Um, and he is the creator of Pest, as well as many, many, many other open source tools that all start with P.
Uh, please welcome Nuno Maduro. Thank you. Oh my god, so good to be here. Lavel live Japan. It's my first time in Tokyo. I love this place already. Your food is great. The weather is fantastic. Having a blast so far. Uh but yeah, it's time to give a talk here. So, let's just do it. I had notes for the Japanese. All right. First of all, I'm going to just fix my slides because they are not displaying. So, let's make sure that's working as expected. Here we go. All right. So, attending a little bit for the slides to display.
Super happy to be here today. The talk today will be about strict engineering. Before we jump into that, for those who don't know me, my name is Nuno Maduro. I am the creator of multiple open source packages that you might be using things like best, things like pint and more. But also, uh, recently I'm trying to become a YouTuber, you know, like recording some videos to YouTube and getting super excited about that. Uh but yeah today we're going to speak about strict engineering. Uh I have a question to you all. Are you guys familiar with a PHP tooling that allow you to have strict code?
Things like PHP stand. How many of you use PHP stand? Raise your hand. I want to see. All right. A couple of you are using PHP stand. That's great. How about things like testing things like PHPUnit? How many of you use PHPUnit? How about past PHP? How about the others? Okay, well that being said, let's talk about strict engineering. Um, because we are actually in 2026, this talk will be more about strict AI engineering. My goal today is give you a set of tips which hopefully are going to make you generate better code using tools like AI.
So that being said, let's just get started, dive into this stuff. The very first tip I want to give you is that just use better defaults in Laravel. We all love Laravel. We love the Laravel starter kits. But in my opinion, there's a few things you can engage, a few things you can improve to make your Laravel apps to be better with AI. And I want to show you a few of them. So, I'm going to move here uh to Sublime Text. Uh just a moment here. There we go. All right, here we go. Moving here to my Sublime Text.
Something that I always do is that I like to configure my app service provider to be a little bit different. So, I'm going to show you a few of those things. I'm going to move here all the way down into my moot method. And within my boot method, I have always this configure models. Let's see what this configur is all about. I'm going to scroll all the way down. And something that I always call is this beautiful directive with a name should be strict. Now the should be strict adds two things to your Laravel app.
The very first one is that it prevents accessing to missing attributes in your eloquent models. And the second one is that it prevents lazy loading. And I want to show you what those two things are about. So I'm going to keep this comment, okay, this directive commented. And I'm going to move here into my console.php. And on this console.php I have a setup of of examples we are going to see all together. Okay. Now the very first example is quite simple. I'm literally fetching uh an user from the database and afterwards I'm accessing this property email which does not exist.
Okay, this property email does not exist should have been called email. Now let's see what is the value returned on the console. So I'm going to just copy this beautiful command. Go to my console. uh terminal here and type PHP artisan missing attribute and as you can see Laravel didn't actually told me that the attribute is missing just told me that the value is new now let's see how this exact code behaves with something like should be strict moving back to my sublime text and this time I'm going to enable this should be strict directive just one line easy peasy okay just one line moving back to my terminal execute the same command but now I have the beautiful Laravel framework telling me that this attribute does not exist and you are making a mistake is much better feedback for your AI coding agent and much better feedback for you all.
Now this is missing attributes but I want to show you uh prevent lazy loading. So moving back into my Sublime Text and I'm going to open again the console.php. I'm going to scroll all the way down and I have this strict lazy loading command and what it does is actually very common Laravel code. What I'm doing here is fetching all the users and then using a for each loop I'm counting all the notifications for every single one of these users. Let's see what happens if I just go here comment once again that should be strict and execute that command on the console.
I'm going to clear my terminal. I'm going to type PHP artisan strict lazy loading. And because I'm logging every single query being executed, I see that I have 12 queries being made. Now 12 queries because I have 10 users. If I have a 100 will be 102. If I have a million will be a million queries being performed. This is literally the biggest cause of app performance degradation in the planet. Okay? And you want to avoid this as much as possible. And to do that is quite simple. I'm going to just clear my terminal. Go back to Sublime Text.
Enable should should be strict. Go back. Execute exactly the same code. But this time Laravel doesn't even allow me to execute this code. It's literally telling you you are doing lazy loading and that's no good. Okay, we want to avoid that. Now, you can also fix the code if you wanted to. Let's actually do that together. I'm going to just modify the query here to load all the users with the notifications. Okay, let's see the result on the terminal in terms of queries. First of all, Laravel now allows me to execute this code. We are no longer within the context of lazy loading.
But I have only two queries being performed. And this is two queries. If you have 10, 100 or a million users will always be two queries being performed. Okay, this is just too good. Okay, this should be strict. It should be just by default on every person on this venue. Now, moving back into my app service provider, I want to show you another one which is I think it's badass. It's very good. It's called it configure commands. And I have this directive here call it prohibit descriptive commands. Now, I don't know about you, but on this area of AI, I'm actually doing multiple things at the same time.
I have three terminals open. Another one that I'm I'm working on a side project plus I'm SSH to a production server doing multiple things. And something that may happen by mistake is that I'm just on my terminal. I type something like PHP artisan maybe something like migrate fresh seed. I say yes and bam. I just lost my job. Okay. I just nuked the database in production out of a mistake and probably this shouldn't ever happened, right? We can implement a concept of defensive on depth to avoid this from happening and it's quite simple by using deck directive.
Let me show you. I'm going to go back into my Sublime Text and I'm going to enable this prohibit destructive commands. Okay, what this directive will do is forbid Laravel from executing destructive commands in your database in production is chef kiss. It's amazing as a tip. Okay, now let's execute the same command as before. I'm going to go back just executed exactly the same command. Clear my terminal. The same stuff in Laravel not even allow me to execute this destructive command. Okay, it's one line of code, no work at all. and you just have to add it to your app service provider.
Now, I hope you guys find these tips useful because in fact, I have a bunch more of them. I like my apps to use carbon immutable by default. I like my password defaults to use something like uncompromised. Equally, I like to configure my testing to be as much sandbox as possible with prevent stray requests, prevent stray processes. And I have honestly a bunch of tips like this. So what I have concluded is that I'm gonna just make a package so all of you can type composer require and have all of this for free. This package have already a million downloads at the minute and it's called Lavel Essentials is one composer required and you just leverage all of this stuff for free.
You don't even know it exists. Okay, just one package. Now this is Laravel Essentials. Um, and I kind of want to move a little bit out of Laravel and give you PHP general tips on this era of AI. Okay. And moving to the very first one which is one of my favorites. Therefore, the question about PHP stand to you all which is types are your AI best friend. Dear people from Tokyo, we are in 2026. All of you needs to know what is PHP stand is the best project that ever happened to PHP since its incarnation after Laravel if I'm honest.
Okay. But PHP stand is just a must know as a PHP developer. So all of you when you go back to work at 9:00 a.m. you grab a coffee and then you learn about PHP stand. It's literally the equivalent of TypeScript for PHP. It just works. So for those of you who don't know what is PHP stand, I'm going to show you exactly what is about. Moving back to my editor and I think I'm going to open this update um update user.php just a regular class, something really peasy and easy. So what I will do here is just make a mistake.
Okay, instead of accessing email, I'm going to accessing something like Japan. Okay, does not exist as an attribute. It's clearly a mistake. And what I will do now I think is just go to my console and I'm going to execute PHP stand and just look how beautiful this thing is. Okay, this is better than AI. PHP stand is literally tell me the following. The property the Japan does not exist. And you might think I know what you're thinking. You might think well my PHP storm also tells me what is wrong with this line. Well that's on the file you are visualizing at that given moment.
PHP stand in the other way goes to your entire project and it tells you exactly what is wrong. This is just the most valuable tool you will learn from this conference. I I'm going to tell you that already. Okay, this is PHP stand. You can enable on the CI and avoid broken deployments if you want to. Now, obviously that is PHP stand, but a bunch of you are probably using JavaScript on the front end too. And for that we have the equivalent of PHP stand call it TypeScript. Now TypeScript is kind of easy. You just install it.
And to kind of reproduce and show you this in practice, I think I'm going to go to my my resources gs maybe pages user profile edit. Okay, I have a bunch of imports here which they are beautiful JavaScript code. And I think I'm going to just replace this use page with just page. Now page does not exist. is not something that can be imported. But I'm going to run TypeScript to see what TypeScript has to say about this. So I'm going to just type this and TypeScript just like PHP stand will tell me two things.
Well, first of all, the page component does not even exist. And the use page that I was using no longer is imported. So just like PHP stand, it really just works. Okay, I'm going to execute the same command. And now obviously I have a green statues and I'm good. Okay, so this is PHP stand and TypeScript and at 9:00 am after the conference this is the first thing we are going to do. Okay, now moving forward to other things that are important on this area of AI which is I love patterns and AI loves them too.
I don't know if you guys have noticed but the very first thing AI does when you ask for something is getting familiar with your project. So we'll see this dude is using PHP, is using some JavaScript, is using Laravel, is using React. But then it will understand your conventions. Do you like uh typed code? Do you are you consistent with your approach naming classes? Do you like final classes? Do you like generics? And it will basically get a general understanding of how do you like the code to be. Now it's important to be consistent on this exact moment.
So the generated code after that point by AI will be just perfect. And I'm going to show you a few things you guys can do to also have this in your AI generated apps. Moving back to my editor here. And what I will do I think is show you my migrations because I have a bunch of opinions on migrations that I love. And you know as a PHP developer I like to always use the class trick types all the way top. So on every single PHP file I have, I use this line. Moving all the way down, I think PHP docs in 2026 are useless.
So I don't use them ever. Also, I like to type my code. It's fully typed all over the place. And I do this not only on this file, but across all the files I have. So if I move here to other migrations, they all look the equal. they are all the same without PHP docs without uh full typed but also like I don't use the down method as well so I'm going to be consistent with that again this is super important so the next code generated by AI will be exactly like this moving a little bit to other stuff uh potentially my eloquent models I like my eloquent models to obviously start with the class types all the way top I like to use property reads to engage the typing of my models Going all the way down, I see final classes.
I see generics being used all over the place. And if I continue to check this, my code is literally like this all the time. I'm going to move here all the way down. I am on this user controller, which is final readon. Um, I'm using form requests all the time. Even if I don't need them, I'm going to still use them. Form requests all the time. I use the action pattern, which is something I haven't invented, but I have popularized it. Um, and basically all my code looks the same. This to say that AI, this is crucial to have AI generating beautiful code in oneshot code for you.
Okay, at the end of this talk, I'm going to actually do a demo to you all so you guys can see all of this stuff being applied on the real feature. Okay, moving from love patterns to something that means a lot to me. Okay, this is my favorite topic ever. So don't um get surprised if I get too excited. I want to talk about the testing pipeline and why that is important in 2026. If testing was important before, now with AI is even more important. It's literally the last safeguard between the code generated by AI and production code.
And a lot of you may think, well, testing pipeline is just about unit tests, but it's not. is about the whole spectrum of quality tools. We're talking about formatting. We're talking about linting, type coverage, code coverage, static analysis, the entire thing. And I'm going to show you this. How do I configure this on my own projects? So, moving again to my editor, I'm going to open the best package manager in the world, call it composer, and I'm going to scroll all the way down. Now let me show you exactly how do I configure my testing pipeline.
First of all, I use something which I don't know if you guys know but it's called composer scripts. Allow me to put some bash commands behind composer. And then the very first one I have it's called it composer lint. Okay. When I run composer lint on my terminal a couple of tools are going to be executed. The very first one reactor PHP to keep my code modern as possible. The second one is Laravel Pint which is a nice name by the way. The third one it's called npm run lint which will execute eslint and preacher which are the equivalent of recctor and laval pint.
So a single composer lint command will execute four tools. Let me show you this on the terminal real quick. Moving here to my terminal, I'm going to type composer lint. And now I have those four tools being executed all at the same time. Now this is important for various reasons, but the main one is if a new team member is joining your beautiful project, he doesn't need to know where things are on vendor or where things are on node modules. You just run composer linked and you have the full spectrum of linking right there. Now moving uh to the other scripts I have uh the second script I always have it's called it test linked which is the equivalent of lint but executes everything under dash- test it's mainly for CI purposes same stuff as before but instead of formatting I'm going to check the format the formatted code moving here to one of my favorite scripts uh with the name uh test uh type coverage it's probably the most underrated feature of past and what it does is quite simple.
It just checks if your entire code is fully typed. Let me show you this in practice. I'm going to copy this type coverage. Moving here to my terminal once again and I'm going to type composer test type coverage. It will tell me well all your project is fully type at all levels. But let's actually just remove a type to see this in practice. Uh moving to my app um update user. I'm going to remove I think I'm going to remove this return type right here. Execute exactly the same command. And now pass php is telling me this code won't go to production because it's missing a type on the line 22.
It literally tells you update user return type line 22. It's missing a type. Now we can obviously just add it back. Rerun the same code. And now it just works uh as expected. This is cool, right? I want a round of applause is for me because I love this tool. Come on. Thank you. So this is type coverage. One of my favorite features about past also belongs on this concept of testing pipeline. Now moving here to other stuff. We talked about this already. Test types will execute PHP stand and TypeScript at the same time. And now all the way down, I finally arrived to the famous unit testing.
And I'm going to execute past PHP with a couple of flags that are very interesting that I want to show you. The first one is dash- parallel. We always all every single one of you have expensive laptop laptops. So let's just run our test suite in parallel to make it faster. I'm going to also use this dash dash coverage to have 100% of code coverage. You are going to see a lot of experts on the field telling you that code coverage is not important. I'm going to tell you the opposite. Is the most important thing on this area of AI is literally what forces AI to have tests for all of the generated code.
Insanely important. Super important. Now all the way down I have the let's say the final command. This command is called it test. And what it does is that it aggregates the full testing pipeline linting type coverage type types but also unit testing just aggregates all commands and allows me to do this. Go to the terminal and type composer test. This will execute the full testing pipeline. You don't even need to know what it is. Execute type coverage linting. The full thing will be executed from one single command. And my friends, this is very useful for three reasons.
Number one, the teammate arriving to your team that needs to know how exactly can test his code. Number two, GitHub actions. We always we love GitHub actions when it's not down. Um, and GitHub actions allows you to execute scripts. And let's make it agnostic. So you can go to this test.l file, which is GitHub actions. And all the way down I have composer test. I don't need to update this file all the time. I can just leverage this and run my CI like I'm running tests locally. And finally, and one last thing I have here which is really cool is this AI guidelines.
So this is Laravel boost. I can tell Laravel boost super important so it doesn't forget at the very end always but always run composer tests ensuring this way that every generated code by AI will be passing all the quality tooling that we have now if you by the way you probably notice how excited I get about testing but if you are also a testing fan there is a video on my YouTube channel which is 30 minutes about this stuff. YouTube.comuru amazing content about testing. Dear Tokyo people, we talked about strict engineering, strict typing, strict defaults, strict patterns, and strong testing pipeline.
I want to show you all of this stuff in action. Okay, so I'm going to do a live demo using cloth code and hopefully cloth code is not down. If it is, don't kill me. All right. So, what I will do here is go to my Laravel app. The exactly the one you are visualizing right now. First of all, I'm going to restart my server because I don't think it's running. I'm going to just do uh this. Oops. PHP. Not this one. Uh uh. One second. All right. Here we go. Hopefully, I didn't screw up.
So, go back to my my Safari. I'm going to type uh refresh here. Type login. I'm going to log in into this uh user right here. There we go. I'm logged in and I'm going to go to this settings profile. Now, our goal today is build a new feature together and see all of the stuff I've been pitching in and talking about in practice. So, under this save button, I'm going to add a new feature, a complex feature with databases, with front end. And the goal is have the give the possibility to the users to add notes, random notes about anything.
So, let's do that together. Moving to my terminal real quick right here. And I'm going to type uh claude, but I'm going to run claude with I think I'm going to run it with dangerous key permissions. I love this flag. Let's do it. So, I have Claude open. It doesn't seem to be down. And what I will do here is that I'm going to ask him build a new feature under profile settings right below profile information. Uh allow the user to add random notes about anything. And I'm going to type enter. And I want every single one of you to take a close look into this.
I'm going to type enter. As we discussed, cloud code will get familiar with the with the with the codebase. As you can see here, we have cloud code listing all the files, getting familiar with the controllers, models, front end, understands you like Laravel, understands you like typing, understands you are using TypeScript. So that's the very first thing cloud code is doing, understanding your project, understanding your conventions. After this uh cloud will start working on generating files. Okay. And we are going to see how those files will actually be exactly like we want. So still reading the files.
Still getting familiar with the codebase. Let's wait here a little bit. Here we go. At some point you should start working on those files already. Here we go. We see creating a note model migration in the factory and we also see create the note action request in controller. Okay. So, it's literally working on on all that stuff. Here we go. Where do we see? Okay, so it's working right now on the migrations, I think. Oh, one second. Okay, it's already working on tests. I think we can see the generated migration already. Let's move here into the generated migration to see if it was exactly like we like and it's not.
Oh, it is. Here we go. So, we see declare strip types being used. This was done by cloud code. We see not PHP docs anywhere which is good. We see full typed code exactly like we like which is very good. Uh we don't see any down method on this new migration. Let's take a look at the model for example. Here we go. The streak types being used all the way top. We also see property reads being generated on this new migration. It's literally oneshotting the feature with carbon immutable as well being used exactly like I have to uh like I like to have my code.
If we move here into this node controller. Okay, it's still working on it. So, let's wait a little bit. But yeah, it's literally oneshotting the feature like um typically like I like. Oh, take a look at this. It's already working on a note factory and it's working on a note factories exactly like I like with extends with final classes. No PHP docs necessary and it knows that I like tests. So, it's basically working on that. Moving it a little bit all the way down, we see working on uh relations, which is good. We see already a form request being created.
So he understands that I like form requests. So it's working on that as well. This form request is hopefully super strict. Here we go with required strings, minimum one, maximum a thousand which is super important. It has a action pattern as well. So the create note is being created as well. Final read only and it's it's doing exactly like I want from actions which is super important. And here we have the note controller as well being coded. Uh we see a form request being used. we see an action being created uh exactly like we expect.
Basically, it's oneshotting the feature just because all of the conventions we love exist everywhere. At some point, I expect him to migrate uh my database. Here we go. Migrating my database and it will start working at some point on the front end. It will uh hopefully understand that we like TypeScript and therefore we'll generate types. And here we go. It's working as we speak on the front end. And I expect him to have types. Here we go. All of this stuff is literally types. Um, exactly like I like to have my code on the front end fully typed, which is very important with the interfaces.
It's it's literally oneshotting the feature, which is super good. At some point, we'll start working on tests. Okay, once it's done with the front end, we should be able already to see the feature um visually on the front end and it will start working on tests. Fully typed front end exactly like we have all the other TypeScript code insanely important and it's already working on tests and because all my tests already have quality, this new test will have quality too. Uh while it's working on tests, I think we can see this feature on the front end already.
So I'm going to click here on refresh. And here we have a random field to add notes. I'm going to just say love you Japan and add the note. And the note was added just below. So just literally working as I expected. Okay. And the code which is most important uh was generated exactly like I would expect. Now very important at the very end we see quality tests using integration controllers in Laravel. And at the very end I expect that once all these tests are created we see a composer test being run ensuring that all the quality tooling in testing pipeline we talked about it's literally right here.
Okay. So let's wait a little bit so we can see that in practice already running linting. So at some point you should run composer test and ensure that we have all of the code behind the here we go composer test being used ensuring this way that all the quality exists on the generated code. Japan, I want to tell you something which you really need to memorize in 2026. I want every single one of you to be engineers top quality. Every single one of you will leave this conference being a top level engineering. And the key for that in 2026 is this thing right here.
Okay. Agent coding is not vibe coding. As such, your responsibility in 2026 is be better than the others. Okay? Every single line generated by your prompts to AI will be generated by you. In that way, you will be a top level engineer in 2026. Japan, my name is Nuno. Was a pleasure to be here. Thank you so much. All right. Thank you, Nuno. Great job. I know cloud code behave a little bit different than the usual. You know, there's no accounting for the LLM. The robot does what the robot wants to do. That's right. That's right.
How was the How was the translation everyone? Was it Did it work? Everyone feel okay? All right. For our uh for our foreigners, we have another Japanese vocab word for you. It's uh soy means like amazing or wonderful or something. So this translation is um okay so Nuno I have a question for you. So you talked a lot about constraints that we can apply to our code bases that sort of uh help us guide our LLM friends uh to behave in the way that we want them to. Right? Um, if I'm say I have a really old, really cruddy legacy PHP application with no tests, yeah, very bad type coverage, no code style enforcement, none of that, you know, but nobody has that, right?
That's, you know, imagine, How many of you have like legacy code bases? Raise your hand if you have a legacy code base. Ah, okay. I have an answer to that. you mind? Okay. Yeah. If if just imagine that you were in such a situation where you had a big messy code base, where would you start? Which constraint would do you think is the most important to start with? Uh I would say PHP stand with this particular feature call it the baseline. Okay. A lot of people think that you need to go PHP stand max from the beginning.
However, you can actually use something called the baseline which is ignore all the existing errors. However, the new code will have the quality expected. So, this exists with PHP stand but also exists even with uh with pint as well. Pint doesn't actually do introduce any breaking changes. Therefore, you can use lot of val pint safely. Um and yeah, I would literally start with the quality tooling I have talked about but on levels that are a little bit um low, you know, just to get started with. Yeah, it's interesting. you seem to have uh known that AI was coming because you've spent uh you spent most of your career building things to sort of create guidelines and guard rails for uh for teams I guess for developers and for code bases uh tests and types and you know things of that nature.
Uh how does it feel now that AI is here? You've sort of everything you've built kind of works together. Well, it does feel good in the sense that AI is at least not coming for the stuff I have built. Yeah. Yeah, right. That feels good in the way. So, I think it's just lucky somehow. Uh, but yeah, it's also, you know, everything I have talked about today is just so much more important than ever now that we don't look at the code anymore almost. Um, so yeah, all of this stuff I'm super passionate about it and I think like um on this area of AI it's even more important than ever.
Totally. Um, how have you how long have you been in Japan? When did you get here? Uh, I've been in Japan for 5 days already. So, having food, having drinks, you know, having fun with friends and I love to be here. Um, I love the people. I love the culture already. So, next trip, my wife is coming a thousand% sure. Awesome. Very cool. Um, all right. We I think we're uh we're just waiting for one more sec for uh the next speaker to come up. So, uh where So, you got in you were saying in Shinjuku, did I see on your Instagram?
Yeah, I'm I was sleeping there. Yeah. Okay. Nice. Um and how was that? You what have you what have you gotten into? What have you seen? What have you done? So, one day was to fix the jet lag. Uh the other day was to get out to go out to a club. The day after was to I was hangover so I literally was another day to fix that. Um and the fourth day was just to walk around, you know, just see the city. You have food as well. Uh the food in Japan is just so much better than I expected for some reason.
It's so good, right? It's so good and it's anywhere. Like almost anywhere you go, the food is amazing. Yeah, it was very good. Um I also like got the chance of speaking with some PHP people from Japan. You guys are very passionate. Okay. You are very passionate about PHP and technology. So that fills my heart with joy. I love that. Awesome. Um, so before this you came from Brazil. Uh, yeah, I was in Brazil for 10 days. That is actually also a big PHP community like all of you uh in Brazil. Uh, the food is different as you may expect.
Uh, but yeah, I went there uh give this exact talk. So people were excited to, you know, learn a few things. That was super fun. And hopefully I'll be back to Brazil sometime soon. Awesome. All right. Well, thank you very much. Uh, thank you, Japan. Appreciate you. Okay, J. All right. Uh, our next speaker uh is our first uh Japanese speaker uh and is the organizer of PHP conference. Um she is uh passionate about uh testing specifically and has given a lot of uh talks about testing at uh Japanese PHP conferences. Uh and she's here to talk to us about testing with mocks and stubs.
So please help me welcome Asaman. Hello everyone. Let's take a picture together. Selfie. I say hi. Z is shutter point. Okay. Hi. Harnessing the power of mock of harnessing the power of mocks and stocks in PHP unit. Oh. Don't move. Just a moment. Wait. Talk together next to the friends. I got it. So you have practiced already. I can't hear your voice. Nice. Thank you. I belong to Rinkage. We are committee sponsor and I we have a we have a some product about preventive healthcare support support and I'm the organizer of PHP conference Odawara and next we will hel April 10th 2027 and actually I usually live as a ninja in Odawara.
Do you know Odawara located in Kanagawa? We have a castle, we have a we have ocean and we have a mountain and beautiful troam. So please come. Anyway anyway my talk is about PHP unit. I have one question. Why do we write test? Someone says to improve quality to reduce bugs because my senior told me to write it. There is a lot of answering but my answer is to make my development process easier. With test we can express how the system should behave in code. With test we can make code review With test we can catch regressions early and refactor without uh fear.
With test we can improve our design. So if it is hard to write test that's a signal you need rewriting or rethinking but there are some problems in writing tests using real things for everything get painful for example unstable slow costly or out of scope so we use test doules in the first half I talk about the difference between mocks and stops and next best testables practices in PHP unit. So let's go to the section one. I describe a very simple keyword. The difference is mock have imitation and assertion and stop have imit imitation only.
That's it. And I brought a quotation from a book uh unit testing principles, practices and patterns. Mox help to emulate and examine outcoming interactions. Both are almost same keyword. Stops behave as imitation only. Stops helps to emulate incoming interactions. And this is in my opinion uh what you assert is what you care about it. So when no test doubles we are clearly looking the whole code but use mocks blood a little about mocked mocked part and used stuff blood a lot broad blood a lot in my opinion and let's compare simple code with create mark and create a method directive is the target for mocking or stopping and it this is also same we return directive is imitation and that's the key point assertion have expect and with have on is on assession so create mock have have express and with sorry it is very simple.
So do you understand whole? So here is la in Japan. So I tell you one keyword in Japanese in this case. Do you know what this means? I am now an expert about mocks and soaps. So you can use when the first time you built hello world in this f in the first code programming grammar. So you have to memorize. Japanese engineer loved that word. So we did. Next topic is when to use mo stops. My answer is whether the dependency belongs to the specification. That's it. My core philosophy test code must express the specification.
leading test should reveal a behavior without product code. I use real object whenever possible. So I prefer classical style rather than London style. But when they are solo or complex, I reach for test doubles. So here is simple question. Do you want to assert it as part of the specification? If yes, use mox. You care about the behavior or side effect. I thought it happened. If no, use stops. You just need a return value. The interaction itself doesn't matter. When this goes right, your test is like a specification. When this goes wrong, let's look at what happens.
I talk about overuse ants. Use well test doubles bring the specification into focus. misuse they do the opposite. Overused mock or stops share one outcome. The test no longer expresses the specification. Overused mock is named fragile test. Refactoring turns green to wet. The behavior is fine. The but the test breaks. The test look like looks in cold earth and order. It knows the inside too well. It decides how it's done, not what it should do. Good test should survive any refactor, but the alpha test can't. Next, overused stops. I don't know how it is named, but I named it blank check test.
Test stay green even when the real dependency quietly changed. The staff freezing the world at a spec specific time. When we did the joy, the stuff doesn't notice. Green humans it run, not it works. Good test should prove the behavior is correct, but a blank check test can't moss let the specification decide. Overuse turns test into a liability, not the asset they should be. The simple check is does this test express the specification I actually care about? And this is my load real object by default. Test doubles only when they get in the way. Tests are messages to your teammate to yourself.
H when you are clear on what spec to convey mock and really start to work for you the light choice shift with your design your layers or your team. So make that judgment together. So it is it is the end of section one. I drink water. Let's go to section two, best practices in the latest environment. Let's review how PHP unit handles mocks and stops. We used to build everything with get mock in PHP unit 4. There is a lot of argument in get mock but actually this time was my first experience of test doubles.
We got create mock at first in PHP unit 5 but we still used create mock at stops. We got create sol at first in PHP unit 8 but als so so we can distinguish from mock but same internal behavior is still same and here is the changes in 10 11 12 13 the point is stuff can't be used by as mock mock can't be used as stuff. Hi. Hi. Here is the changes step by step. Best practices for handling mocks and shops in PHP unit are evolving. PHPUnit is getting intentional about the the distinction. Not just just naming it but enforcing it at the API level.
That means bajon upgrade now come with a cost you all that will need to express intent. Let's walk through what that looks like in practice through my own migration. Uh January of this year I tried to upgrade PHP to 8.5. So I have to upgrade PHPUnit to 12.5 and after I run test here is who I was shocked I think it is asat like asot there is a lot of there is a bast number of PHP unit notices after I run the test 615 PHP unit notices appeared and PHP unit said no expectation were configured for the mock object for hona consider refactoring your test code to use a test stop instead and that attribute can be used to opt out of this check.
So here is my example test code. I made I made shared mock in setup. Specifically that example have process mock and cat mock and in test I use this get sut method and these are example test. This test has all mocks properly configured because uh catmok is configured, process mock was configured but this test has some mock unconfigured specifically catm. So PHP unit notices appeared. Every mock now requires an assertion. This makes sense but it completely breaks the way we used to write test. A mock with no expect means effectively a stop. So it triggers the PHP unit notices a lot of that issue that migration reality is happening everywhere.
This is an uh PHP unit issue. Erh people were in trouble with about dealing with mock without expectation notices that situation was as same as my situation and there are two solutions one replace use create sub for assession two opt out using that attribute that's it and that is also PHP unit issues how to ignore all mock without expectation notices at once solution. There is no way to do that in PHP unit. Deal with each notice one by one and that is issue in Symfony. Uh Symfony were in trouble with uh same situation and they replaced create mock with create stop in each module and this is in dupal issue.
They are same and they are same. Uh they replaced create mock with create stop in each module. Cake PHP is a little different from before. First of all they replace they replace but after that ended up using mockery. How was Ravel? Railway smoking helpers are built on mop not PHP unit native mocks so no issues about that and come back to my issue what I did PHP is highly motivated to draw a query line between mock and stops I asked myself what makes a good test a good test expresses the specification to do that test doubles must express intent too.
So I committed to fixing every notice step by step. This is my migration steps. Uh first of all bulk add the opt out the opt out attribute by a custom rep because I want to finish upgrading PHP 8.5 and then next replace what vector PHP unit can replace and then and then fill that attribute of one by one and then on to PHP unit 12.5 Five lect php unit o com convert create mock to create stop it reduced the account and is worth trying and when I used that tool they didn't support intersection type so intersection type so I sent a pre pull request and it is it was merged so you can you can use with intersection type support and now we are on PHP unit 13.
so uh I introduce three highlights in migration of PHP unit 13. Migration point one the any major is hard duplicated from 13. This is but example test code because the test use any uh any expression. So you have two choices two two choices. One make a mock complete specifically not use don't use any expression. Two, make a stop complete. Specifically, remove expective migration point two with without expect is hard duplicated from 13 uh that version. And this is example about example test code because no expect. So you also have two choices. Make a more concrete with ex expects or make a stop complete specifically remove expect and with migration point three at least with a non-positive argument is hard deprecated from that version actually I I didn't faced face that issue but I I introduced that uh that is But example test code because uh at least arguments is zero.
It is nonpositive number. So you have you also have two choices. Two choices. Oh yeah. Make a mock complete or make a mock. Make a stuff complete. Hi, my m my migration points are three. As I said before, it crosses off ambiguous smoke at the specification level. Assert with create mock imitate with create stop. Now enforced by the API. Takeaways when you assert and imitate use create mock only when it is part of the specification. It always parries expect or exactly always parries expect drop any drop at least with non-positive arguments when you imitate only use create stop for dependencies you don't need to assert configure with method and we return nothing else never write expect never use with that's it so Hi, summary.
I write test code to make my development process easier. If I need test double with imitation and assertion, I use mock. If only imitation, I use stops. PHP unit is evolving to distinguish stops from mock. Let's make a clear distinction between them. you know what to say. Repeat after me. Say, wow, nice. Great. Awesome. And oh, I love PHP unit. Thank you, Sebastian, for create awesome test framework. and he gave the keynote speech in PHP conference odor this year. So scan the QR code everyone because I uploaded the video on PHPCTV. So you should watch it.
You have to watch it. You must watch it everyone. Do you have a smartphone? Everyone please and watch it. Very nice keynote. And I brought PHP unit collaboration march for my hosted conference. So if you come to me and said your ass is very nice, I will give you the sticker. I want to I want to speak a lot of people. So talk to me. Thank you. Enjoy your two days. Well, AIT. this Okay, everyone. Uh, thank you so much. Uh, we are now going to go into a break until 11:30. So, Um, everyone having fun so far?
All right, cool. Um, all right. So, go forth, get some coffee, get some water, speak to our sponsors in the back here. You can speak super loudly right now because there are no talks going on. So, if you want to yell at the sponsors, now's a good time. Um, all right, cool. Thank you very much. And I will see you back here at 11:30. Heat. Hey, Heat. Can't feel inside. It's time. Are you M. Mime. M. I just want to make you mine. I just I want to make you I make you I want to make you I make you I make you I make I just want to make you I want to make I just I just want to make youineh I'm just I want to make you I want to make you Heat.
Heat. Heat. I make you I be It's ow. make you mine. Mine mine. I just want to make you mine. My my make you I make you I make you I make Make you make you mind. I want to make you my I just want to make youine. I just want to make you I want to make you I just want to make you I want to make you Hey Data Nas. up hey down. Hey Hey, Heat. Everybody Dancing. down. My mind. make you I make you I make you. my I want to make you I want to make you Hey.
Merry Christmas. All right. All right. All right. All right. All right. How we doing everybody? We good? Okay. John, I've got another vocab word for all of the foreigners in the audience. Everyone ready to learn a word? Okay. So, our our next word is geni. So, genki is a Japanese word that doesn't exactly translate to any English word. Um, but it means it can mean a lot of things. Um, but one of the things it means is sort of like feeling good, excited, energetic, um, buoyant, bouncy, um, effervescent. So, uh, one of the ways that Genki is often used is that when you meet up with someone, they'll say, "Ah, Genki," which means, "Are you Genki?" Uh, and then you'll say, "Hi, Genk." Which means, "Yes, I am Genky." Right?
So, I'm going to ask all of you guys. All right. Good job. And I'm I'm glad that you're all so ginky. Um, Ginky Ginky. Um, all right. That's great, J. All right. Um, our next speaker is a great friend of mine. Uh, we've spoken together at many LACons all across the world. Uh, I think at all of them, right? Um, and uh, she hails from the great nation of Australia down under. Uh, she rides motorcycles. She's very cool. Um, and she works on the Laravel Nightwatch team. Please help me welcome the one and only Jess Archer to talk to us about Clickhouse.
Ohio cuz I must Jesse. Good morning everyone. I'm Jess uh and I'm from the Laravel team and today I'm here to talk to you about Laravel Nightwatch and how we built it. For those of you that don't know Laravel Nightwatch, uh can I get my slides up on the screen? So for those of you that don't know, Laravel Nightwatch is a first-party application monitoring tool made by Laravel for Laravel and it monitors the three key pillars of observability. So exceptions, uh, logs and performance monitoring. Now this means that we collect a lot of data from a lot of our customers applications and since we launched in June last year we have ingested over 481 billion events into our database.
So we only hold up to 90 days of data at any given point in time. But right now our largest single database table in our largest region has 46 billion rows. This is 24 terabytes of data uncompressed or one terabyte of data compressed. So you might be wondering how do we ingest all of this data from all around the world into uh our database. So it looks a little bit like this. On the left we have your Laravel application. You install the nightw watch package and it listens to all of the events that Laravel is emitting about what is happening.
It packages these up and it sends them over to the nightw watch agent. This also runs on your uh your server whether it's uh your own server or Laravel cloud, Laravel Forge and this allows your observability data to be sent from your application very very quickly to a local agent. The agent then buffers that data up and sends it every 10 seconds to our infrastructure starting with the ingest endpoint where the data is validated. uh we make sure you have quota, you have an account uh and then we put the data onto CFKA. So we put it onto a variety of different topics on CFKA and from that point we then use a service called Click Pipes.
Click pipes reads the data from the CFKA stream and inserts it into our database and in this case our database is called ClickHouse. So you might be wondering what is ClickHouse? Click House is an analytical database also called OAP or online analytical processing. It's very different from the traditional transactional databases like MySQL and Postgress that we are typically used to seeing. Uh it is used by massive companies such as Cloudflare, eBay, Lyft, Vimeo, Microsoft and so on. And in the case of Cloudflare, they ingest over 11 million rows per second into Clickhouse. At Nightw Watch, we ingest about 22,000 events per second.
So, we're not quite at cloud filler levels, but uh still very impressive that Click House can handle all of this data. Now, my favorite things about ClickHouse is that it is free and open-source. It also has excellent documentation, which is also available in Japanese. And we found it to be faster and cheaper to run than any of the competing products that we evaluated. So, you might be wondering, how fast is it? So on my laptop right here I have a MySQL server, a Postgress server and a Clickhouse server with the same data set loaded in so that we can see the performance in real time.
So to start off, let's have a look at the shape of our data. I'm just going to run this simple select statement to just get the first 100 rows from this requests table. We can see that it's a simplified version of the type of data we collect for nightw watch. So we have the timestamp of a request, the URL of the request, the HTTP status code, and the duration of the request. Now in this case, we can see this query took 3.9 milliseconds. So very, very quick with MySQL. Let's see how many rows it's reading, though.
So we'll do a select count from requests, and I'll get this one running because it can take a little bit of time. So 3.1 seconds to count that there are 20 million rows in this database. So it took a little while for it to count that. Let's now ask Postgress for the same count. And we'll see Postgress was a fair bit quicker. 252 milliseconds. Uh the same 20 million rows. And now we'll ask Clickhouse for the count as well. And we can see Click House counted it in 1.3 milliseconds. But ClickHouse gives us some extra information with the query results.
It tells us how many rows it read and how much data. And in this case, we can see Click House only read one row. So Click House is cheating here. It didn't actually count all of the rows. It has an internal counter. So, let's make it do a little bit more work. Let's add a wear condition. And this time stamp is just 1 second into this 31-day data period. So, this means it can't just look at its counter. We'll see that it still ran this query in 9.2 milliseconds. And we can see that it only read 8,193 rows.
It's an interesting number. 8,192 is a special number in Click House. It's called a granle. And Clickhouse will generally read data in chunks of 8,192. So in this case we can see it read uh the one row to get the overall count and then it just read the one chunk at the end to figure out what it had to do. So ClickHass has a lot of tricks up its sleeve to make itself fast. But let's get into some more interesting queries. So this is with MySQL. This is a typical uh query we would use in nightw watch to populate a chart or a graph.
So we're going to select the uh date of the from the time stamp the total number of requests for that date uh the fastest, slowest, and average durations. So we'll run this query now. Again, this is with MySQL uh reading those 20 million rows. So it takes a little bit of time with MySQL. So 8 seconds and we got our results back. Now, if you're just doing a query uh for curiosity or for uh your boss, that amount of time is probably fine. But if you're building a real-time dashboard and maybe there's lots of graphs on the page, this is way too slow.
Let's see how Postgress handles the exact same query. So Postgress is not too bad with this amount of data. Uh 693 milliseconds. Uh so now let's have a look how clickouse handles its exact same query with the same data set. We can see click house only took 81 milliseconds. And this time we can see it did read all 20 million rows in that table. And if I go back and run it again, it's even quicker this time because the query cache has warmed up. So let's talk about how clickouse is so fast. There's a lot of reasons, but the main reason comes down to how the data is actually stored on disk.
So it's a difference between row orientated and column orientated. In a row orientated database which is our transactional databases like MySQL and Postgress the data for each row lives together like this. In a column orientated database like click house the column data lives together. So the data for all of this column lives together. This lives together this and so on. To look at this in another way imagine our row orientated database like MySQL is a single file on disk with all of the data concatenated one after each other. We can see we've got row one, then row two, then row three, all after each other.
In a database like MySQL, it's very fast to get to an individual row because all of that data lives together. The index helps it scan to this exact spot and we get all of the data for that row. But when we want to do an aggregation query where we want to select a column from uh a lot of different rows, it now has to skip over all this irrelevant data, grab that duration, skip over more irrelevant data, grab another one, and so on. If we compare this with a column orientated database, each column is a separate file on disk.
So we can see our uh we have the row data for just that column in each of these uh in each of these column files. Now when we want to aggregate on an individual column, all of that data lives together. We don't need to skip over anything. We can just go and grab that data out nice and fast. But conversely, if we want to access data for an individual row, we now have to go and read that from all of these different files, which is why you generally don't want to do select star with ClickHouse.
You want to select the exact rows that you want. And generally in Click House, you're not dealing with individual rows. You're much more dealing with aggregates of a lot of rows. So now let's talk about how data is actually inserted into Clickhouse. Every single time you do an insert, it creates a new what they call part, which is a directory on disk. So every insert is a whole new folder on disk. These parts are immutable. So uh when you want to change them later on, there's uh some special considerations that Click House has to do to make this happen.
But these parts get merged together in the background. So ClickHouse does a background merging process and combines all of these smaller parts into bigger and bigger parts. Now the way data is indexed on clickhouse is also a little bit different. So the primary key in click serves uh not only as the index but it also defines the order of data on disk which is very very important in click. The primary index is also sparse. So the primary index only points to every 8,192nd row on disk because the entire primary index needs to fit in memory.
Again because you're not generally reading individual rows at a time. This is the optimization they have done. There are also other indexes available data skipping indexes and projections that can help you with uh different query patterns. But your primary key is the most important tool in Clickhouse and you need to optimize it for your most common query patterns. So what happens if Clickhouse isn't fast enough? I have this other table here. I've called it requests XL for extra large. And I'm going to count how many rows are in this table. So this one has 1 billion rows.
So let's see how Click House handles this. So we're going to run the same chart query that we ran earlier, but now on our 1 billion row table. And we can see this took Click House 1.8 seconds and it read all 1 billion rows. That's still pretty good, but if you're again building a real-time dashboard, that's not fast enough. So, ClickHouse uh still needs extra help to make it faster when you get to larger and larger volumes of data. But just to show you how Clickhouse can be uh optimized, if we add this additional wear statement, so we're going to select just one hour's worth of data out of this 1 billion uh row data set, which is for 30 days, we can see this query still runs really fast.
So, it doesn't really matter how much data is in this table. We can still query it really fast if we scope it down. But when there is when we want to query a big bulk of data then we need to use other techniques. So let's look at the structure of this table. So we've got our uh requests Excel table. We've got the timestamp of the request, the URL, the status code, the duration and in this case we're using the merge tree engine. This is the base engine in Clickhouse uh that all other engines kind of uh inherit from and this uh is named after that merging process.
Uh this is kind of the best engine for storing raw data coming into the system. And then we define our primary key here which in this case is time stamp which makes this data really quick to query when we're filtering by time stamp because it can effectively exclude all of the other rows that are irrelevant. We're then going to create an aggregate table. This will store pre-agregated data which is going to help us make things faster. So we're calling this one requests Excel by minute. We're going to aggregate the data by minute. So instead of time stamp, we're calling this bucket.
This will represent a bucket of time. In this case, 1 minute's worth of time. And then we're going to store the number of requests. The sum of requests uh for this minute. Uh sum is a simple aggregate function. It doesn't need to uh have a lot of state to combine multiple buckets together. You just need to have the total number in there and we can combine them together to get the new sum. Same with fastest, which is the minimum duration. Slowest is the maximum duration. And then the average duration. This one's not a simple aggregate function uh because to store an average and combine multiple buckets together, we need to store a little bit of extra state.
So average is a uh is just uses a regular aggregate function. The engine here is aggregating merge tree. So again, this extends from the merge tree. And in this case, our primary key is on the bucket, our time stamp column. To get data into our aggregate table, we can create a materialized view. Materialized views in click house are a little bit different than other databases. They are just an insert trigger. When data comes into one table, the materialized view will just insert that data into another table. So in this case, we're calling this requests Excel by minute.
The destination is our requests Excelby minute aggregate table. And then we define where the data comes from. Uh so we're just going to select we're going to take the time stamp, but we're going to round it down to the start of the minute to be the bucket that it belongs to. the uh count of requests in that particular insert, the minimum duration, the maximum duration, and then the average duration for that individual insert from our source table, which is our requests Excel table, and we're grouping it by bucket. So to see how this works, we will insert two rows into our requests Excel table.
Those will go into the raw data table as those two rows. the merge uh the materialized view automatically kicks off and then that aggregates that rows and inserts it into our aggregating merge tree and because those two rows were the same minute and it got rounded down to the same minute they get inserted as a single row. If we did another insert for the same minute that would be an extra row in that table but the merge process will continue to combine those together. Any rows that share the same minute will just get aggregated together and collapsed.
So let's now query run our chart query on our aggregate table. So remember this is still 1 billion rows worth of data but now we have pre-agregated it. And we can run this query and see that this only took 15.8 milliseconds. So it's the same result as querying the raw data but much much faster because we've pre-agregated it. And we can see that it read 44,640 rows which happens to be the number of minutes in 31 days which is the size of this data set. So, how do we handle updates in a database where the parts are immutable?
There's a few different techniques Click House has for this. They have uh concepts of lightweight uh updates and heavyweight updates. A heavyweight update will actually rewrite the parts. This is generally very bad practice in Click House because uh it puts a lot of strain to tell it to rewrite everything. There are lightweight updates that will effectively apply a mask over the data. when you query it, it will apply that and at merge time, it will kind of resolve that and write the parts. Um, but when we've got a lot of event data flying into the system and we just want to be able to update things, we can actually update by inserting.
So, let's look at this uh users table. This is an example of where we would store uh your user data. So if you have users of your application and we want to store the uh username and the name we have our so we have the ID column of the user the username and their name and this lets us when you're looking at an individual request in nightw watch you can see which user made that request. This time we're using an engine called replacing merge tree. This is a really cool engine in click and our primary uh key is the ID.
Now the primary key on a replacing merge tree does define the order of data uh on disk and defines the index but it also defines the behavior of the table. So any two rows that share the same primary I uh primary key will get collapsed together into a single row where the latest one wins. So let's look at this in practice. Let's first just select star from our users table. And we can see that there are no rows in this table. I'm now going to insert two rows into here. So, one for me and one for Taylor Otwell.
So, we'll insert those two rows into the table. And now, we'll query the table. And we can see there's two rows in here. Now, I've put my name in here as Jessica Archer. Uh, but that's what my mom calls me when I'm in trouble. So, I'm going to rename I want to rename this to Jess Archer, the name my friends call me. So, to update this particular row, I can just insert a new row that has the same primary uh key, in this case, one, with my updated name. So, I'm going to insert this And then we'll query our select star from our users table.
But we can see we have three rows in here. We don't we didn't update the existing row. Click house doesn't want to rewrite…
Transcript truncated. Watch the full video for the complete content.
More from Laravel
Get daily recaps from
Laravel
AI-powered summaries delivered to your inbox. Save hours every week while staying fully informed.









