[0:00]Hey everyone, welcome back to the channel. Uh, for those of you who may be new here, I'm Evan, I'm a former Meta staff engineer, and I'm the current co-founder of hellointerview.com.
[0:09]If you're currently preparing for software interviews, and you probably are if you landed here, then head over to Hello Interview.
[0:15]We have just about everything that you could possibly need, the overwhelming majority of which is totally free.
[0:19]Uh, in this video, though, we're going to be covering message queues, and specifically, as always, in the context of system design interviews.
[0:26]And so, we're going to start with a motivating example that'll show you why queues exist in the first place, and then we'll talk all about what a message queue actually is, how it works under the hood.
[0:33]When you should use one, and then finally, we'll get into those deep dives that interviewers love to probe into, things like scaling, back pressure, ordering, durability, all of that good stuff.
[0:44]So, without further ado, let's get after it. We'll start things off with a little motivating example.
[0:49]I want you to imagine that you're building a photo sharing app like Instagram.
[0:52]So, these are uploads of photo to your server, and then it needs to do a bunch of stuff with that photo.
[0:58]And so, for example, you may need to resize it into multiple different resolutions, you may need to apply filters, maybe run some kind of content moderation checks in the background to make sure that it's appropriate, it's not nudity, those sorts of things.
[1:10]And each of those operations takes a couple of seconds each.
[1:14]In the simplest possible architecture that you could design, what might happen here is that the client uploads the photo to your server, and then your server does all of that work synchronously.
[1:23]That single server handles all of that work, resizing the images, applying the filters, running the moderation checks, and then once all of that's done and only once all of that's done, it returns the response back to the client with the success message.
[1:37]This, this works, kind of, but it has some real limitations.
[1:42]The the first is latency. The user hits upload and then they just stare at a spinner or whatever you put on the client, while all of that processing is happening and they're just waiting.
[1:50]Nobody wants to have to wait six seconds just to get that confirmation that they're they're they uploaded their photo, right?
[1:56]The second problem is around how fragile this is.
[1:59]What happens if the filter service maybe crashes halfway through all of that processing?
[2:04]Well, the whole upload now fails. Now the user ends up getting an error with a message maybe to retry, and that resizing work that we already did is now totally lost too, and we have to start from scratch.
[2:16]And then the third one is, is a big one. How do you manage really bursty traffic? So, imagine that, for example, your app gets featured in the App Store, super cool.
[2:24]Um, but now your upload spike from what was maybe 50 a second to 5,000, or 50,000, or 500,000 a second, and your servers, they can't handle more than maybe 200 per second.
[2:37]And so, those other 4800, right? They're just timing out or they're failing or the user gets an error.
[2:44]Your system's basically falling over under the load because it can't handle this new huge throughput.
[2:51]So, with all of that in mind, let me show you how we can solve each of these problems by introducing a message queue.
[2:58]Instead of processing that photo immediately, what if when that upload comes in your server just saves the file and writes a message to a queue?
[3:06]The message is something simple, like, hey, photo 456 needs processing.
[3:11]And then our server can immediately respond back to the client saying that it's done.
[3:16]The upload's complete from the client's perspective, and we can show them maybe the single resolution photo just to them while the rest is processing in the background.
[3:23]Because at the other end of the queue, you have a pool of workers, maybe a worker servers, right?
[3:28]where each worker is pulling one of those messages at a time off of the queue and processing it.
[3:33]So, if three photos get uploaded around the same time, each one gets picked up maybe by a different worker on the other end of that queue, called consumers, and they'll all be able to process in parallel.
[3:45]So, we can look at what happens in this case to our three problems. Now, uploads are fast because your server is just saving the file and dropping it onto a message queue.
[3:51]It's not doing the expensive processing.
[3:54]Failures are isolated because if a worker crashes while processing a single photo, that message just gets redelivered to another worker and it picks up where the other one left off.
[4:03]And then on those big traffic spikes, it just means that the queue gets a little bit deeper, right?
[4:06]There's more items in the queue.
[4:10]And so, the messages sit there potentially waiting to be processed, so at worst, there's a delay, but none are dropped or erred out.
[4:16]All right, now let's formalize what we just saw.
[4:19]What actually is a message queue? Well, it's pretty much exactly what it sounds like. A message queue is just a buffer, a queue that sits between a producer and a consumer.
[4:28]The producer is the thing or the server, the service that creates the work.
[4:33]In our example, this was that server handling the upload from the client.
[4:36]And the consumer is the thing that actually does the work.
[4:39]In our case, this was that pool of workers that process the photos.
[4:43]The way it works is really straightforward. The producer sends a message to the queue and then totally forgets about it.
[4:49]It doesn't care when or even if the message gets processed at all, that's not its responsibility.
[4:54]It just fires and moves on. On the other end, the consumer pulls messages off the queue and processes them at its own pace.
[5:00]So, the queue's whole job is just to hold on to these messages until somebody is ready to deal with them.
[5:05]It's just a buffer in between the two services. The key property here is called decoupling. The producer and the consumer don't know about each other, they don't need to.
[5:13]And so, this allows you to scale them independently, and swap one or the other without affecting each other directly.
[5:20]You need more consumers, fine, you can add more servers there while leaving the producers where they were.
[5:24]You need more producers, you can scale those up while leaving, you know, the one or two consumers that you had.
[5:30]Um, to wrap up this, this kind of intro on what is a message queue.
[5:34]Uh, in, I'll, I'll be it kind of silly analogy that I remember from school, which may help you and I've seen this click for candidates.
[5:41]Is to think of it like a kitchen. The waiter takes your order, and then puts it on the ticket rail. The cook grabs the ticket off of the rail when they're ready.
[5:49]And the waiter doesn't just stand there waiting the waiting for the cook to make your food.
[5:52]Instead, they go and they serve other tables, right? And so, the ticket rail decouples the front of the house from the back of the house, exactly the same way a message queue does for our producers and our consumers, right?
[6:02]Pretty straightforward example. Okay, now that we know what a message queue is, let's talk a little bit about how it actually works under the hood.
[6:08]Uh, there's a few mechanisms that you need to understand and each one solves real problems.
[6:14]So, let's start off with with acknowledgements. Let me give you a scenario.
[6:18]A worker pulls a message off of the queue and it starts processing the photo.
[6:21]Halfway through, the worker crashes for whatever reason.
[6:24]It runs out of memory, anything can happen here. And so, what would happen to that message?
[6:29]Well, if the queue just deleted the message the moment the worker grabbed it, then that photo is now gone and it will never get processed.
[6:35]That user that user's upload is basically just lost forever, uh, which would clearly be, be really bad.
[6:42]This is what acknowledgements solve. When a consumer pulls the message off of the queue, the queue doesn't delete it right away.
[6:47]Instead, the consumer has to explicitly send an acknowledgement or an ack back to the queue, saying, hey, I'm done with this one.
[6:55]You can go ahead and actually delete it now. So, if the consumer crashes before sending that ack, the queue assumes it wasn't processed and it ends up just being redelivered, that message ends up being redelivered to another consumer so that nothing was actually lost.
[7:08]Great. So, the the queue holds on to messages until consumers ack them, right, acknowledge them.
[7:14]Um, but think about what this actually means and you may have already thought this or or recognized this.
[7:18]While worker A is busy processing a message, and it hasn't acted yet because it's in its four seconds of doing all of that processing, then that message is technically still in the queue.
[7:28]So, what's stopping worker B from grabbing it too?
[7:33]And then you would have two workers doing the exact same work, which is wasteful at best and in some cases, maybe even even dangerous or hurts the state of your system.
[7:40]Now, different queuing systems solve this exact problem different ways.
[7:44]In SQS, which is Amazon's native message queue, when a consumer picks up a message, it becomes invisible to all other consumers for a configurable window, like say 30 seconds.
[7:55]And so, if the consumer finishes and it acts within that window, then all good, the message was removed.
[8:00]If it doesn't, the message becomes visible again automatically, and another consumer can retry.
[8:06]So, there's basically like a 30-second window or a configurable time period, um, where we we don't let consumers, um, double process a message.
[8:14]Kafka on the other hand, they take a pretty different approach though.
[8:17]They just assign each partition, we'll talk about what those are in a second, to exactly one consumer in a group.
[8:24]So, there's no even competition in the first place. There's only one consumer ever reading from any given logical queue, if you will.
[8:31]And then RabbitMQ, another popular message queue that we'll talk about at the end, they use channel-level pre-fetched limits and act time-outs to manage this.
[8:39]So, we won't get into all those details, but what's good for you to know is just that um, all of these queues have a way to prevent duplicate processing.
[8:47]And whenever your queue of choice is, it might be worth looking up how exactly they do that.
[8:51]So, while the implementations differ, the concept is always the same. Every queuing system just needs a way to make sure that a message is only being actively processed by one consumer at a time.
[9:01]Okay, but even with acts and that duplicate uh, message prevention, there's still a tricky edge case that I want to make you guys aware of.
[9:09]So, what if the worker processes the message successfully, but then crashes right before that moment it sends the acknowledgement, it sends the ack?
[9:17]Now the queue thinks that it was never processed, so it redelivers it to another consumer, and that same photo gets processed twice.
[9:24]And maybe in our case, when you're just resizing photos and running content moderation, that doesn't matter at all.
[9:29]Doing that twice has, has no bad effect.
[9:32]But what if the message was something like charge Evan $50 for a banking application or something?
[9:38]Um, that duplicated message now just resulted in me being charged $100 and and that's obviously not cool.
[9:44]Um, this is the problem that's referred to, as we talk about message queues, as delivery guarantees.
[9:50]And there are three that you should know about and that your interviewer might ask about.
[9:54]The first and by far the most common delivery guarantee is called at-least-once delivery.
[10:00]This just means that the queue guarantees that every single message will be delivered at least one time, but it might be delivered more than once.
[10:10]The implication of this is that your consumers now need to be what's called item potent.
[10:17]Item potent just means that processing the same message twice will produce the exact same result.
[10:22]Let me give you an example. If your message says, set user 123's profile photo to photo five, then running that twice is fine.
[10:31]You get the exact same result. The first time you ran it, it set it to photo five, the second time you ran it, it just set it to photo five again, which it already was, so no big deal.
[10:38]But, like we saw with that earlier message, or with the banking example, if your message is something like, increment user 123's post count by one, then running that twice is a problem.
[10:48]You've now obviously incremented their post count by two.
[10:51]And so, in practice, you design your operations to be naturally item potent, like in a photo example, or you check whether the action has already been completed before doing it again.
[11:02]And so, if we, if we take that example of increment user 123's post count by one, the message or the work would actually be, uh, update user 123's post count to 54, where 54 was what it was before, plus one.
[11:17]Right, that way running it twice, the outcome is always still 54.
[11:21]Um, now, this at-least-once delivery with item potent consumers, this is almost always the right answer both in production and in your interview.
[11:30]So, if your interviewer asks what you're going to use, it's almost always the right answer to say, I'm going to have at-least-once uh, delivery guarantees, and I'm going to make sure that my consumers are right and potent.
[11:38]The second delivery guarantee is what's called at-most-once.
[11:41]And this is basically just fire and forget. So, a consumer takes a message off of the queue, we immediately delete it off the queue at that moment.
[11:47]If something goes wrong, you know, at most, one guy processed it.
[11:51]Uh, at worst, nobody processed it.
[11:54]And so, you really only want to use this for things like analytics events or metrics where losing a few data points is totally acceptable.
[12:00]You have to be able to accept the loss if you use at-most-once.
[12:04]And then the third one is the holy grail, it's exactly once.
[12:07]Uh, this is that every message is processed exactly one time, as it says, right?
[12:13]Uh, the reality is that true exactly once delivery is extremely hard to achieve in distributed systems.
[12:20]Kafka supports a form of it for specific patterns within its own ecosystem, but it comes with real trade-offs and limitations.
[12:28]And so, my honest advice to you is don't promise exactly once in your interview unless you can explain the mechanism and defend it.
[12:35]At-least-once with those item potent consumers is the safer and frankly, the more practical answer and what is almost always used in production.
[12:41]Now that we understand a little bit about how queues work and what goes on under the hood, the next question is, when should you actually reach for one?
[12:47]Well, there's four signals that you should end up looking for that may lead you to introduce a queue in your interview.
[12:54]And these are very similar to the motivating example that we started with.
[12:57]The first one is that async work. And so, this is when a user doesn't need an immediate result, like sending an email, generating a report, processing uploads, all those things that we talked about.
[13:08]Uh, the litmus test is really simple. Ask yourself, does the user need the result of this operation right now, or can they wait a little bit?
[13:16]If the answer is no, then it's a great candidate to put it in a queue and have a worker process it asynchronously.
[13:21]The second is the bursty traffic like we saw in our example.
[13:24]You need to absorb spikes in traffic without dropping any requests.
[13:28]And so, the queue is there to kind of smooth out the load by acting as a buffer and just accumulating a backlog of work that the consumers can get to, you know, when they have time or they have resources.
[13:39]Third is decoupling. This is your producer and consumer might have completely different scaling or hardware needs.
[13:46]Going back to our image processing example, the upload services are super light-weight.
[13:50]They just accept the file, drop it into a message queue, but the workers doing the actual processing might need GPUs or beefy machines with lots of memory.
[13:58]And so, with a queue between them, you can scale and provision each side independently.
[14:02]You're not forced to run expensive GPU instances just to handle uploads.
[14:07]This could make it more cost-efficient.
[14:10]And then the fourth one is reliability. When you just can't afford to lose work.
[14:14]So, if a downstream service is temporarily unavailable, the queue holds on to that message until it comes back online and you make sure that you never lost anything.
[14:24]One thing that I do want to call out just really quickly, because I see it in quite a few interviews, especially with junior and mid-level candidates.
[14:30]And it's be careful introducing a queue into a synchronous workload, it just doesn't belong there.
[14:35]So, if you have strong latency requirements in your non-functional requirements, like sub 500 millisecond response times to get an answer, by adding a queue, you nearly guarantee that you're going to break that constraint.
[14:46]Not only do you have a bunch of complexity on figuring out how to get that message back to the clients in the first place, but you've broken that latency almost entirely by the nature of the way that these systems work.
[14:55]So, again, queues are for that work that you can afford to do later, even if later is a few seconds from now.
[15:02]Okay, now let's get into some of those deep dives.
[15:05]This everybody's favorite part, right, the things that the interviewers really love to dig into, once you introduce a queue into your system.
[15:11]So, it's really important that you're prepared for these questions, right?
[15:14]You just drew a message queue on a white board. Here's what the interviewer might come at you with, okay?
[15:19]So, the first one's about scaling. They might say, how does your queue handle the increased throughput or handle increasing throughput?
[15:26]And well, you need to recognize here is that a single queue can only handle so much.
[15:30]When you need more, you do what's called partition.
[15:33]And partitioning just means splitting the queue into multiple independent sequences or like kind of sub-queues of messages.
[15:40]Different workers can then process different partitions in parallel, so that your throughput scales horizontally with the number of partitions.
[15:49]So, by splitting into multiple queues, I'm putting that in quotes just because we're kind of conflating terminology here.
[15:55]But multiple partitions, thus multiple logical queues, you can have multiple consumers consuming from the same time and thus increase throughput.
[16:04]Um, on the consumer side, you have what are called consumer groups.
[16:08]And a consumer group is just a pool of workers that divide those partitions amongst themselves.
[16:13]So, if you have six partitions and three consumers in a group, then each consumer can handle two partitions.
[16:19]You need to go faster? Well, then you can add more consumers.
[16:23]Now, importantly, there is a ceiling here. You can't have more consumers than you have partitions.
[16:28]If you have six partitions and six consumers, adding a seventh doesn't help you here, because there's no partition left for that new consumer to consume from.
[16:37]Right? Hopefully that makes sense. Now, importantly, the partition key, which is how you decide which message goes into which of these partitions, is really, really important.
[16:47]It's analogous to choosing a shard key or partition key in a database, and it matters for two main reasons.
[16:53]The first is ordering. Messages with the same partition key always go to the same partition, and within a partition, ordering is guaranteed because they're sitting in that same sub-queue.
[17:05]So, imagine again that you're you're processing that bank transaction example we brought up.
[17:10]A user maybe deposits $100 and then withdraws $50.
[17:14]Clearly, they should be able to do this. They put $100 into the bank, now they want to take 50 out.
[17:19]If those two messages though ended up on different partitions, then the withdrawal could get processed first, and now it's rejected.
[17:26]Because at that moment, maybe the account is empty, right?
[17:31]And so, by using account ID as the partition key, now both that both of those messages will land on the same partition, because they're pertain to the same account.
[17:39]They'll be in the right order, and they'll get processed in that right order, where we add the 100 before we take away the 50, right?
[17:46]And then the second one that's important about choosing your partition key is the even distribution.
[17:51]You want your partition keys to spread work across these partitions pretty evenly.
[17:56]You can imagine that if you're building like a a ride sharing application, and your partition by city, then now New York City is going to be, excuse me, New York City is going to be absolutely slammed, while Boise sits there, maybe getting nothing.
[18:10]Right? And so, that's what we call, of course, a hot partition.
[18:15]And you'd probably want to partition by something more evenly distributed like a ride ID so that you don't have that hot partition where you have one consumer doing all the work where another consumer is just sitting there waiting because it's just watching Boise and there's not nearly as many Uber rides.
[18:27]Right. Um, there's of course a real trade-off here though, and it's one that you might discuss in your interview.
[18:33]And it's that the key that gives you ordering might not always be the key that gives you the best distribution.
[18:40]And so, choosing the right partition key here is one of those decisions that's worth really spending some time in your interview, thinking through the consequences on those two factors, ordering and distribution.
[18:51]The the next deep dive that interviewers love to ask is, what happens if your producers out-pace your consumers?
[18:56]So, if your producers are creating messages faster than your consumers can process them, the queue the the the queue just grows and grows and grows and grows, right?
[19:05]And the queue doesn't solve a capacity problem, it just delays it, it's just buying you time.
[19:11]If you receive 300 messages per second, but your consumers can only handle 200, that queue is growing at 100 messages every single second, and you'll never be able to catch up.
[19:21]Eventually you'll run out of memory on that queue, and things are going to go wrong.
[19:25]So, what what do you do or what can you do?
[19:28]There's a couple of things. The first, of course, is scaling, you can, you can add auto-scaling, and a lot of the cloud providers provide auto-scaling, where you monitor the queue depth, and when it starts to grow too much, you spin up more consumers so that you can consume quicker, or you can even add additional partitions to the queue.
[19:44]But the second one and the one that interviewers are often times looking for is to apply what's called back pressure to the producers themselves.
[19:52]And so, slow the producers down, basically start either rejecting messages or maybe returning an error to the client, saying, hey, we're a little overloaded right now.
[20:01]Please try again in a minute. And then the third and maybe the bare minimum is that you should just be setting alerts, of course, on your queue depth so that you know when something like this is happening.
[20:08]It's good to have the monitoring and the alerting here.
[20:13]Um, be ready, be ready to discuss this one. Interviews want to know that you understand that a queue isn't just magic, right?
[20:19]It's a buffer, not a solution to insufficient capacity.
[20:24]Moving on, uh, sometimes a message just fails to process.
[20:28]And so, your interviewer might ask you, what happens when a message fails to process?
[20:31]Maybe the image file was corrupted or the downstream service is temporarily unavailable.
[20:36]That's fine. It, it happens, right? So, think about our photo upload example. What if I just uploaded a corrupted photo? It will never succeed. No matter how many times you try, it will continue to fail.
[20:48]And this is a really common problem, and it's what's called with message queues a poisoned message.
[20:52]Sounds maybe scarier than it is. But it's just a malformed or problematic message that crashes the consumer every single time and there's no recovering from it.
[21:00]So, without guard rails, it's going to retry forever.
[21:03]And meanwhile, everyone else is just stuck behind it waiting.
[21:07]It's just consuming all the resources of the given consumer indefinitely.
[21:11]To solve this, most queuing systems, they let you configure a max retry count.
[21:16]The message gets tried, tried, tried again, maybe five, six times.
[21:20]And if it still hasn't succeeded after five tries, instead of retrying forever, you shunt it and you put it to a dead letter queue or a DLQ.
[21:29]And a DLQ is just a separate queue or sometimes even just a separate partition where failed messages go, so that somebody can inspect them later and figure out what went wrong.
[21:38]Meanwhile, the main queue keeps moving. So, if this is failing, don't put it back into the main queue, put it somewhere else where we can just wait and maybe an admin comes in later to see what's going on there and try to fix those, right?
[21:48]Or nowadays, an AI model. Um, mentioning this proactively in your interview is great.
[21:53]It shows that you have a bunch of seniority, it shows that, hey, I'm going to have a limit on retries, I'm going to add a dead letter queue here.
[22:00]Um, this shows that you can understand those those failure scenarios. Now, speaking about failure scenarios, what about the ultimate failure scenario?
[22:04]Right, what happens if the queue goes down?
[22:07]Um, and this is a question about durability and fault tolerance, especially if that was in your non-functional requirements, it's something that you're going to want to talk about.
[22:14]And it's good to know that modern message queues, at least some of them, like Kafka, they persist messages to disk, and they can replicate them across multiple brokers.
[22:23]So, what it's called in the Kafka ecosystem, but these are just different servers.
[22:26]So, if one broker goes down, another replica has that data.
[22:30]Just like with read replicas with databases, same concept. So, in this way, no messages are lost.
[22:35]Uh, Kafka in particular is interesting here because it stores messages on disks with a configurable retention window.
[22:42]So, you could keep messages around for say, a day, a week, even forever if you wanted to and you had the capacity.
[22:48]And what this means is that you actually can replay messages from the past too, which is a really powerful recovery scenario.
[22:55]Uh, if you need to reprocess data after kind of something went down, you have a new new version of a consumer.
[23:00]And so, you can imagine that your consumers go down for a while, they're offline for an hour, your queue, your Kafka queue is just backing up, no big deal, because when your consumer comes back on, it can start to just take all of those things again.
[23:11]Even more so, if that consumer was broken and it processed things incorrectly, well, we can just put a new consumer in, tell that consumer, hey, reprocess back from an hour ago, even though the messages were consumed, um, and we can kind of fix what we broke.
[23:27]Speaking of Kafka, let's maybe quickly go through what are the most common message queue technologies.
[23:33]You certainly don't need to know all of these for your interview, um, but you should have at least one that you're comfortable talking about.
[23:38]If you don't have a default already, choose Kafka, it's kind of like the interviewing industry standard.
[23:44]Um, but let me walk you through a couple of them.
[23:47]Of course, starting with Kafka, Kafka is probably the most widely used, and it's the one that I said, I'd recommend.
[23:52]Um, it's a distributed streaming platform that can act as both a message queue and a stream processing system.
[23:57]So, it's built for really high throughput.
[24:00]It's durable because of what we talked about, it writes messages to disks, and then it scales via partitions.
[24:05]Right, when we're talking about partitions, that's how Kafka works.
[24:08]It also supports those consumer groups. Um, but one thing that makes Kafka a little different from a traditional queue is that messages aren't removed directly after they're consumed.
[24:17]So, this was that example where you want to replay messages in case something, some code in the consumer changed, right?
[24:23]Um, and Kafka, they stick around for those retention periods.
[24:26]So, multiple consumer groups can read from the same data independently, and you can replay messages if you need to, like I said.
[24:34]Um, the second one I'm going to call out, and we have this in our written breakdowns quite a few times is SQS.
[24:39]This is Amazon's Simple Queue Service. It's the AWS hosted ecosystem version of a message queue.
[24:46]Um, it's simple, it's fully managed.
[24:49]There's no infrastructure you need to worry about. It comes basically in two flavors, a standard queue, which gives you the best effort ordering and really high throughput, or FIFO queues, which give you strict ordering, but at a lower throughput.
[25:00]So, SQS is a great choice when you want something really straightforward. You don't need more advanced features and your interviewer is cool with you pulling uh hosted solutions from cloud providers.
[25:09]The last one that that I'll mention is RabbitMQ.
[25:12]And RabbitMQ is a more traditional message broker and it supports complex routing patterns through what it calls exchanges and bindings.
[25:20]Obviously, I'm not going to have time to get into that here, but it's all the same underlying concepts.
[25:24]It's maybe less common in system design interviews, if I'm going to be honest with you, I hear it less.
[25:28]But it might be worth knowing that it exists, especially in cases where you need some sophisticated message routing logic.
[25:35]So, to wrap things up in this section, if you don't already have a go-to, pick Kafka, it's the most versatile.
[25:40]If you want just hyper simplicity, and the AWS ecosystems around, SQS is great.
[25:47]It has that visibility time-out thing that we had mentioned earlier, it has the option for ordering guarantees or looser guarantees, but higher latency.
[25:53]All right, there you have it folks.
[25:56]Um, hopefully you found this useful, just a really quick recap. Message queues decouple your producers from your consumer, they buffer bursty traffic, so nothing gets dropped.
[26:04]They distribute work across pools of workers.
[26:07]Um, you should know when to use them, know the pitfalls, be specific and detailed when you bring things up.
[26:14]Um, any questions, anything that you think I got wrong, go ahead and please drop those in the comments.
[26:19]I respond to as many of those as I can. Uh, you'll have the X calidraw drawings that I use in this video down in the description as well, so go ahead and check that out.
[26:26]You'll also have my LinkedIn, connect with me, send me a message. Again, I respond to as many of those as I can get to as well. I love hearing from you all, especially if you have a success story to share from your interviews, I love to celebrate with you.
[26:37]Uh, most importantly, good luck with the upcoming interviews.
[26:40]You guys are going to do great, you're going to nail it, you're putting in the work, um, and I'll see you soon.



