Thinking about Complex Addons in Xano

Ray Deck helps Erhan fix a Xano add-on that returns no results because its input mapping is null. The real issue: the add-on uses an inequality filter that forces a full table scan and can't use indexes. Ray shows how to debug with run-and-debug, measure actual performance (0.75 seconds for looping), and decide when an add-on is worth the complexity.
Chapters
So this segment is another time that I did guest mentoring over at the Xano Office Hours, and the gentleman who I'm helping is looking to augment, you know, data pulled from one table with information from another. And ordinarily, add-ons are a pretty easy way to do that in Xano, but he's finding that they're fighting him because of those more complex needs. As a result, we look at this, we try to make the add-on work, and then we turn around and just start using the actual function stack for the job, because that's actually one of the very special things about Xano is that it's pretty good at data manipulation and allowing you to reshape data without too much ceremony using the basic primitives of conditionals, if-then, and looping. Once we put those together, he was able to get his, uh, solution. And then we had sort of a broader discussion about different approaches, uh, for managing performance, which he was otherwise concerned that using the function stack would drag down. I hope you, uh, learned as much from this session as I did. Uh, Ivan, how can we be of service to you today, sir?
Cool, I feel good already. Okay, uh, so I'll show mine. Um, oh crap, I'm not sharing my screen. There we go. Okay, share. Okay, I hope you can see my screen.
Uh, it's coming up, I believe. Okay, here we are, and I can see myself. Hello, me.
Okay, cool. So, uh, I have, here we go, I have an add-on here which is called CacheSourceAccount. Basically, this is taking the cache instrument ID and the timestamp, which it is, and then I'm calling this in a, yeah, here we go. So I'm querying all records here from cache instruments And what I'm doing here is in the output, I'm just doing a very basic, uh, add-on from what I just showed, which is taking ID, last_counted, and it should give that output.
So the only problem is the ID of what? The ID of last_counted? Can you show me that one more?
Okay, it's just taking these two.
Yeah, those are the inputs of the function, but then it was the add-on that was very confusing to me. Uh, you're routing data add-ons input, uh, and add-ons input tape wants to match based on the instrument ID and based on the date. Is that what you're using last counted for?
Last counted, yes, last counted. So, so basically, uh, what, what I'm trying to do is, is this— I'll probably show that here in the add-on. Okay, here we go. So in the add-on, all I'm trying to say is, uh, I want to get everything from cells instrument ID matches, and the sales created date at is created after the last counted.
Got it, I'm with you. Yes, please continue.
Okay, okay, cool. So when I do it here and I copy, uh, you know, an example of that last counted timestamp, which is just, uh, this. So I've just copied the last counted from in there. So, oops. This is moving on its own. There we go. Yeah, so when I run this, you can see that's the output that I get, uh, you know, for instrument ID 5. It shows me those items. When I try it here— so my cursor is not behaving. Okay, so when I try it here and I run this for instrument ID 5, which is here, I get nothing in the sales.
Okay, you get nothing in the sales based on last counter, which is from the input. And what's the input that we gave to this particular function?
The input that I get is this last counted.
Yeah, but I don't know what that value is. Let's scroll to the very top of your input results. Over on the very right-hand side, you can scroll to the top. We can see what the inputs are that you passed to this function when you did it.
Sorry, sorry, this button?
It's null.
Yeah.
So perhaps we change that to a 0. Maybe that will give us an interesting result.
Yeah. So actually, my bad, I should not even be calling this last_counted in here. I should not. And I'll tell you why. If I take this last_counted out, Sorry, how do I hide this piece? Sorry, my mouse seems to be moving on its own for a bit. Like that. If I take this out.
Well, if you take that out, then how is it supposed to know what the last count is coming from?
Because it's supposed to get it from the table.
But that's not what you're asking it to do right now.
Yeah, no, no, so I've taken it out. I was just trying to test it there.
Yeah, but now we can take a look at it, but like, uh-huh. Yeah, uh-huh.
So then the last counted should now come from—
no, it now comes from the text called cat last counted, and you want to just come from cache instruments last counted.
So it should come from here, this last counted. Yeah, in the table.
So probably it was coming from the input before as opposed to coming from cache instruments, and that was most likely the source of your problem. But let's see. Save that there, then let's try running it.
Yeah, and run it. I go to 5. It's not working. Yeah, so, so the only reason I put— yeah, so I'll just show you something. So you can see that's the last counted. If I just copied this, that's for demo purposes, and then I come to, uh Do this again, and in the output here— Gosh, my mouse is just having a mind of its own. Sorry, man. Oh, wow. Okay.
Wonderful.
So, if I come to the output here—
We're happy for you, Erhan. Oh, wow. Congratulations.
Oh, wow. Okay. I'm not sure if it has anything to do with me sharing, or is it just one of those days. Okay, so if I go to output there and go to that, if I change this last counted and hard code it to that value, save, save, and rerun, I'll get the output there. So when I hard code it, I get the value, but when I try to refer to that column I get nothing.
Okay, well then there are two major options available to us. One option available to us is if the add-on's not working, you know, and like we look at the add-on, seems like it should be working. I mean, one thing you can do is raise a ticket with the good folks at Xano. Maybe there's something weird going on. But the other thing you can do is if the add-on's not working, you can, after you do your query all records, simply loop over your records and go pull your payments one at a time. Just by doing query all records and then like merging that into the greater dataset. That's all the add-ons doing under the covers, right? Okay, so the, so you think that was the automate for you, make it do manually?
Yeah, no, you're right, and that, that is where I started from. I was just, I've been told somehow, or I'm not sure if my understanding is correct, I thought the add-ons would be a much more efficient way of of doing that?
They're not efficient. And not for nothing, the add-on, as you structured it, because it's operating on an inequality, is going to necessarily be quite inefficient, right? Because it's forcing a table scan in order for it to work. Because efficiency in databases is driven by using indexes, right?
Okay.
So whenever you ask a query that you can get from an index, for example, in your cash payments, if you're able to, the foreign key, if the cash instruments field is also indexed, then that will cause that query to go fast, right? But if you then say, oh, and where X is greater than this amount, then it won't be able to index on that because you can't say it is here. You can only say that it isn't, right? Because that's the nature of an inequality from a logical point of view. So first, there's not a lot of performance to be gotten because of the nature of the way this thing is built. And second, using an add-on versus using it yourself will not have a huge difference in performance. But as always, you should keep an eye on like how long things actually take and which things are the bottleneck for the user experience. But either way, I wouldn't super overoptimize for it. Like this thing right here, this is a, this is an API query that's running, you know, a dozen queries in sequence. This one's going to be slow.
Yeah, that's, and that's, that's a problem. That's why I tried to, I thought, I mean, so this works, it gives me the result I'm looking for. I thought to make this less slow, I was going to turn all these into add-ons and I thought that would help with that.
Well, you can, you can experiment with which add-ons work and you can also experiment with which ones drive performance for you. Um, but like all an add-on is doing is first it gets the data from the database and then it turns around and runs the, the add-on query. And, and really it's just sort of, you know, saving you the time of having to go back into no-code land because Xano is a little bit like Python this way in that there's a cost of going from line to line. So putting things inside a line usually makes it go faster than going from line to line. But it keeps on getting faster and most of the time that's not gonna be the bottleneck for your user. So the way I would do it is allow it to be slow. See what drives performance for the user, and then go back to figure out which things are driving the most. One more thing I might do just before we leave this topic is if you could just scroll to the top and do a run and debug— stop and debug— sorry, run and debug for me.
Uh, from this one or from the other one?
From this one.
Okay, from this one.
It doesn't totally matter. Uh, you can, as long as you set up that it can run a little bit. Um, if you take a look, you have a stop and debug in there. Could you just Take that for a second. Yeah. And then we'll run it one more time and then take a look at the debugger in the upper right-hand corner for me. Yep. One of the very cool things that we'll do is I'll tell you how long these things take.
Right.
So right now, you know, you're for your, the whole loop that's running on step 3 is taking about 3/4 of a second. That's not super, but it's probably not holding up your user perception of user experience.
Okay.
Right. So you want, you want to pay attention to which ones are taking much longer. Those are the ones you want to ask. Okay. And then within the one that within, within a query that's taking a long time, what was the section that's taking a while? And when that section, what are the pieces? And those pieces can be caused by things that go slow and things that have that, that repeat a whole lot, right? Like loops that just fire over and over and over. Um, and, and those become like your triggers, like where you're going to have your sharpest opportunities. To be improving your performance. So don't worry about trying to optimize for performance from the get-go. Allow the code to tell you where it's slow or having a hard time, and you'll find that just a few cuts of that can drive a lot more performance. It kind of like we were doing with Aaron, the subtraction approach is, and, and, and just a simplification as opposed to introducing lots of fancy new tech, is often the easiest way to get both better DX for you and better UX for your customer.
Okay, cool, understood.
So hopefully that gives you like a few, a few tips and tricks you can use along the way there.
Yep, for sure. Awesome, cool, thank you.
My absolute pleasure, sir.










