Convex is agentfriendly. Convex is a gamecher for spinning up AI prototypes. Convex is so good at using AI. It allowed me to vibe code instead of worrying about SQL. So the words getting out agents are really good at writing Convex apps. But wait, aren't agents like an all powerful Uber developer? Shouldn't they be good at writing apps with anything? Yeah, they're actually not. So, LLMs actually do suck at writing software in some ways, but I'm going to share with you today three specific tricks in Convex's design that make them work anyway. Let's dive in. So, if LLMs are not all powerful, what are they actually good at when it comes to coding? Well, here's my take. So, LLMs are clearly um incredibly broad, far more broad than any person. Imagine this just goes way way way up, right? What do I mean by this? Well, LLMs are incredible at a lot of different domains, right? So, like I LLM's definitely know Vue better than I do. I might know React about as well as as LLM. So, in terms of like the amount of stuff they know, right? They know an incredible amount about everything. This is useful for us sometimes as professional engineers, but to be honest, we're normally working on similar kinds of stuff. And so, actually, most days we're probably underleveraging their breadth, right? Like the fact that they're also good at writing Shakespearean poetry or something doesn't really help me very much when I'm just like trying to make a web app. Most days I'm trying to make a web app. I'm tending to do similar kind of tasks. Yesterday is today, but they are incredibly broad and that's nice when you need it. But when it comes to depth, I'm going to put LMS about here. Okay. So, what I mean by this is now that we're in our domain, right? Let's say um we're making a web applying the right best practice to solve the right problem. Um they are quite good. And this is maybe one of those big discrepancies, right, that people see that I think when you're a um new engineer um you're actually kind of down here and you think LLMs are incredible at like knowing best web practices and doing the right thing for any given task. Um true experts are normally stronger than LLMs in any given domain, right? So we're always more impressed by LLMs outside of our domain. We're like it's incredible at chemistry, right? But then like people that are, you know, chemical researchers are are like, "Yeah, it knows a lot of things, right?" But it's not necessarily producing new ideas or close to them. Now we get to the good stuff. So like anything computerized, what's actually incredible about LLM is their speed, right? And in particular, their speed for their price. So they produce, in this case, code so much faster than any person could. I mean, this is this is their actual superpower. We can't always tap into their breath, right? Because we really are focusing on a narrower subset than everything an LM can do on any given task, but their speed is always good and and everything else follows this. But maybe the most surprising take is it when it comes to context. So, LLMs are significantly worse than the best humans at context. Um, and what I mean by this is that that if it's in the training set, right, they're just so good at so many things that are in the training set. Um, but once we start getting project specific, this is kind of all last mile short-term thinking. um strong engineers are still incredible about understanding a much larger codebase and like creating all these kinds of compressed artifact layers about like what parts of the codebase do what job and I know where to go look if I'm changing something and I've got a sense of like altering this code will affect this other code in this other part of the project right so LLMs are way way worse than strong engineers at this job right now and this is maybe like the biggest limitation of LLMs in practice when it comes to software engineering. It's part of why LLMs are so good at simple projects, right? When everyone's trying to make a to-do list, um it's a well-known pattern. So, it's got it in the training set. It's quite good at it. And uh it produces them very fast and there's the context is very small. The first version of a project is not very big and all the considerations need to be made are are sort of like can be traversed well by the LLM. So, some of the things I'll walk through with you about how Convex makes LLM successful despite their limitations are really going to refer back to some of these these particular weaknesses, right? Especially this weakness. This weakness is very very important. This should act as another useful reference point, right? Convex is not the only thing LLMs are good at. So jQuery has been around a long time. For those of you that have only been web developing more recently, you might not know about jQuery, but jQuery is a hugely popular uh web uh client side web application framework that was uh ruled the world from 2007 to even even now. Um, and LMS are not great at making websites with jQuery, unlike some other technologies, certainly compared to, let's say, convex. There's a lot more jQuery code in the world, right? So, there's a lot of code in the training set, right? But yet, LMS don't generate working websites with jQuery nearly as well as they generate working sites with React. Similarly, classic distributed systems, okay? Um, classic back-end programming where you've got a constellation of services, application servers, caches, cues, databases. LLMs don't generate back-end code that well. Uh, they can make code, but a lot of times it doesn't work. Um, and they are good at convex. So, one thing you might ask yourself when you just see this highlevel handwavy thing is, is this because Convex is kind of like the React for backend programming? And the answer is 100% yes. After all, I mean, Facebook and the React team designed React to solve this really big problem, right? And that problem is composition. I mean, it's in the name components, right? composition is the central big step forward that React offered in the web development space and that modularity and composition is exactly what Convex does for the back end. So here are three big specific ways in which the Convex's design and React's design help LLMs be successful via composition. So, Convex's first magic trick is Convex provides agents great feedback about building software. Agents are probabilistic processes, right? As I'm sure you're very well aware. And the difference between the best model being used by an agent and the average one is 86% right versus 93% right. Right? So, we still get it wrong a lot of the time. And as we all have been discovering, things like types and stuff like that are some of the best ways to give agents a feedback loop to be able to just change change things a little bit and run again. Read the type error, make the correction. And in convex, absolutely everything is defined in code. So writing your schema is specified in code. Defining HTTP routes for your backend is just in code. Defining background jobs like cron jobs is in code. Heck, you can even have sophisticated agentic workflows that are just an npm install away and then you write code. All of that code lives in the same codebase. It shares all the same types including all the way back to the database with the schemas. And so when agents generate code, if they get it a little wrong, they immediately have type errors that tell it what to address, they're able to take that, make an adjustment, and then in general, once the compiler is happy, the project is pretty close to correct. That provides an fantastic feedback loop by making everything code ccentric that traditional backend engineering doesn't exactly provide. But, you know, the way we've always built backends before, you might have an EngineX config for your HTTP traffic, and then you've got maybe you've got Terraform to deploy infrastructure. Maybe you've got a bunch of YAML for all of your uh Kubernetes configs. Maybe you're using Confluent Cloud for cues and so you've got another dashboard over there with topics that you've set up and then you're using Amazon maybe for something. So you've got elasticashe and RDS and VPCs and AM and all this kind of stuff to figure out too. You can end up having different configuration languages, different dashboards and LLMs don't know how to really get to this stuff and how to manipulate it. And not only that, but some of this stuff is only relevant in prod and it's not relevant in development. So any feedback cycles that come from this stuff might not apply once you go live in convex dev and prod work exactly the same way. So there's never any incompatibility between the kinds of configuration you have to test in one environment versus the other. It's always consistent and it's always in a single language which is regular TypeScript. It's always typed to provide type feedback. And speaking of types, it's not even just about different configuration languages and different dashboards and systems. And it's also just regular old in our app, right? So like in the way that we build most backend and full stack apps is we've sort of got something like JavaScript or TypeScript on the front end, right? With some state model that's maybe calling some kind of designed REST endpoint, right? With a series of all of these are type systems, right? like how do we translate these into HTTP parameters? Um, and then we parse those things in a backend language. It might be the same or it might not as our client. And so there's another type system to sort of map these parameters and semantics to what the application server is doing which finally eventually has to uh land in our database, right? Which is using yet another type system, some kind of like uh create table SQL type system. potentially we may use a OM to make this bridge a little easier to manage, you know, which again is just this desperate need for more coherence between our types that are automatic, right? So, um we could use TRPC or something like that to make this bridge more automatic where we've got the same thing on the front end to the back end. Convex just it glues all this together automatically, right? So this is what we mean by end toend types is if you if I make a change to the databases types my my UI code the very front end of the stack will show squiggles and a type error and I could see that in my editor but guess what agents also see that and so the amount that agents are able to generate to propagate state changes comprehensively all the way from the very top of the stack the human sees to the place where it rests on disk is extremely complete. complete in convex versus any other system. So yeah, convex provides agents a lot of feedback and agents are probabilistic. They don't get it all right and they generate it differently every time and they're able to address a problem that has data associated with it to close the gap on whatever they got wrong the first pass. So feedback is crucial to them being successful. In convex, your entire application is is code, right? And LMS are very good at code. Um it's all in one place. There's no dashboards. It's all in your codebase. Um it's all typed and it's typed end to end. So there's none of these glue layers where like the application server is typed, but then there's a kind of adapter that turns it into REST or turns it into SQL. It's all one thing. LLMs love that, right? It allows them to iterate until they're successful. Um, and a brand new thing that we're rolling out in convex is if you imagine these classic distributed systems with your cache over here and your queue over there, your app server here, your database there, the clients over here. There's no one's really in charge, right? So, no one really understands how all these things relate to each other except maybe the developers that wrote it. the system. It's seven independent systems. There's no cohesive integrated understanding about what's happening in Convex. There is because Convex ingests this entire typed data flow system including the front end and the back end. And because of that, we can give the agents runtime information. So if part of your site is slow, we we see all of it. we see the relationship of caching to the database to the client and we are able to provide uh extremely uh directed information to the agents to be able to automatically fix production issues. Um and because convex is a system that involves a lot of determinism, it's really easy for us to do things like replay traffic with a change that an LLM proposes in order to tell the LLM, you sped it up and guess what? you didn't change any of the logic, all of those transactions would work exactly the same. And so this kind of runtime feedback is something we're just starting to play with now. But feels incredibly powerful in terms of where we're going to be able to go with it. Convex's second magic trick when it comes to LLM's working with it is that convex enables local reasoning. What is local reasoning? Well, the way I would put it is local reasoning is actually what is essential to composition. It's what React got right. And it's what fixes this fatal flaw right here. The fact that LMS are so bad at context. So, this is the big idea in a nutshell and maybe kind of a secret about convex. So many people hear reactivity and now we have backend reactivity and think great it's good for real time UIs like chat apps right or games and it's cool that it's easier to build those things with convex don't get me wrong but reactivity its big win is not really about real-time UIs that's not really what we're excited about at convex reactivity actually means you have managed data flow and that means data is just always where is supposed to be. Even if the UI isn't reactive, the fact the entire system now is reactive because the back end is participating in it makes a whole lot of problems go away. And in particular, managed data flow is actually the secret behind the ability to support local reasoning when you're either writing code or an agent is. And when you have local reasoning, when local reasoning is sound, that means that everything everything is in the context window. Everything the LLM needs to know is right there in the function they're working on. Let me show you what I mean. So this is from the React tutorial. Most basic component you could think of, right? Takes a value, renders a button, has that value as the label of the button. How does value get set? This component doesn't care how value gets set. It can do anything it wants with value. Could could render millions of buttons, right? It doesn't matter how value gets set. It just knows that it will always be showing the correct value of value. How does it know when it's time to rerun? It doesn't need to know that. It just expresses what it does with value. React makes sure that this thing reacts when value changes, right? So, React is providing manage state of flow here also. So, this is probably a state variable. It could very well be a state variable, right? So there's a set state somewhere that might update this. Whoever decides to change that state, whatever that distant code is written by some other team and some other mo module potentially, right? Do they need to know how many things are using that value? No, they don't. they just set it right with within their local use effect or handler for a, you know, some kind of text entry or whatever their use case is or even a backend value updated, right? Um, they just know they can feel free to set state anytime they want and anyone throughout the whole project that was dependent on that value and was using it for something meaningful to the problem they were solving, they they'll just automatically encapsulate the state update. Right? So this managed data flow thing where producers of values don't have to really care about where the consumers are and consumers of values don't really have to care about the places the value might change is what allows you to take large code bases and make small local changes without understanding the entire codebase. And that's that's exactly what LLMs need. LMS are most successful when they can just look at one function or one comp module maybe or one component that's in the context window and they just know if they generate syntax right here and it types checks transforming one value into another value then they've done their job. Um and convex makes that happen because the database is reactive. The entire backend also gets this property where you can work on a convex function without ever needing to worry about what mutations might affect that function. You might think, is that actually unique to convex? And yeah, it is pretty unique to Convex. Let me give you a good example of why this could be a problem with traditional backend engineering. So, I'm going to admit I got a little lazy here. I actually just asked an LLM, Opus46 in this case, to just give me an example and it actually made a pretty good one. So, let's look at it together. So, a real time dashboard, right, with derived data. So, we have a collaborative project management tool like linear or a sauna. And when a user changes one task, that's it, just one modification from in progress to done. Um, we need to make sure to change a few things, right? So the percent done project uh progress bar on the UI it needs to go up a little bit. the team members like uh contribution the fact the team member did one more job or whatever like that a sprint burndown chart there's a slack notification there's an activity feed right so this one mutation causes several things to happen um and you could imagine in a traditional architecture right we've got our client and then we've got an app server we've got our database we've got a cache so that when everyone's loading these dashboards, they load nice and fast. We maybe have some kind of message Q service. And uh sorry that the formatting here is a little screwed up, but um but you this is like Kafka or whatever. It's a Q and there's some workers. It'll notify Slack maybe asynchronously update the activity feed and do some calculation like aggregates, right? Rerun the aggregates and then update the cache. So once you have all this stuff right now, let's just say we make one change. Let's let's say that we had a new done tab which is like um abandoned, right? Well, as soon as we add this new state, we need to be pretty careful that all the kind of cascading implications of how this is calculated. Like it may be that we make this one change in one part of the codebase, but there's implications for how all these other calculations work that um are outside of the context window when the like abandoned function is being written. It it forgot to invalidate some of these values in the reddis cache, you know, uh it forgot to update the slack notifier to handle the new case, right? So um so what might happen is you actually don't invalidate the cache because the um the app server um wrote a second or third or fourth version of handling a state transformation of the task from in progress to abandon instead of done. the bigger your application gets, the the more like the LLM somehow remembering all the places that make assumptions about a change here and its relationship to change like state here, its relationship to background work in some other system and like um and then um what happens when that other job that's maybe not even running the same server finishes calculating stuff? Does it know all the right values to update back in here and in here in order to reflect all those values back to the client? Right? So data flow ends up being one of the biggest contributions to the need to reason about your the change you're making locally and all the other places that essentially have a kind of data dependency on that change happening. And this is actually kind of why LLMs aren't great at jQuery either, right? jQuery like made it much easier to build web apps because it kind of made some nice highle APIs that were standardized across all browsers but but they still were state dispatch was still up to you right so they didn't manage state dependencies the way react does and so you still had to kind of manage these graphs of a change you know in this form needs to update all of these three other pieces of UI right and so you ended up building your own like graph management libraries or whatever for like propagating state changes and stuff like that. And as you can imagine, once you have thousands and thousands of lines of code and and maybe um 50 people all working on the same project, no one can remember all the things that depend on all the other things. And so everyone is looking to make the world cognitively more simple. Right? When I do my task today, all I really need to keep in mind is just the stuff about my new task and not the whole project because the whole project starts to get too big to remember how it all works. LMS have an even more extreme version of that problem because they're just not quite as good at compressing context into knowing, oh, if I change this, I should probably go look at this other stuff. But part of why again the Facebook team made React and made it so com componentoriented and so compositional and so amunable to local reasoning is that once teams and code bases reach a certain size even human ability breaks down to do this. LMS are just much worse at it. So you get the benefits much sooner. All right, magic trick number three for why LLMs work so well with convex is convex minimizes the amount of stuff going on in the meta layer. This is probably the most abstract idea of the three, but it is actually a distinct third idea. It's kind of interesting to think about. Let me let me give you my best shot at walking you through it. I'm sure you all know 1 + 1 equals 2, right? What does 2 plus 2 equal? I mean 2 plus 2 equals four. But the reason you know that isn't because you've seen every combination of numbers before, right, in your life. Uh like you've probably never added 137 and 413. I don't know if I have, but we could probably figure it out together. that is going to be uh 550, right? Yeah, that looks right. So, but I know how to do that because um I understand the meta layer above these constructions, right? So, I understand that there's a like symbolic system for how to combine two numbers together using addition. I know how to sum two numbers, right? Um so this is I guess the this written form of this like consider this kind of the object layer right these are instances of the sort of symbolic system that's abstracted one layer above this which is like how do you combine any two things using this plus operator um x + y equals some z and we're we're sort of taught the system for composing these things you all have probably seen the things out there too to expand on this idea that like if you give LLMs checkers, right? Like they're pretty good at playing checkers, you know, um but if you give them a game that's simpler than checkers that you just invented, they're often hilariously bad at playing it. And checkers is such a popular game that not only do they have a ton of training data at the object layer, there's also a lot of training data out there in the meta layer. There's a ton of stuff out there about how to play checkers, right? So, it's, you know, checkers has a very large combinatorial space, right? Like the number of board states and checkers is enormous, just like the number of board states in chess is enormous. So, um there's I haven't done the math, but I'm pretty sure it's impossible that every single checker board state, let alone chess board state LLMs have seen, but they've seen a lot of them. And then they've also seen a heck of a lot of content about the rule system, about the meta layer, about in general what what do all the states mean and what are their relationship to each other and what are the strategies and what are the so so both the object layer and the meta layer are in the training set for well-known games and you could take a simpler game that you just invented that a human would learn pretty quickly and an LM often will be quite bad at. So traditional back-end programming with all of these different interconnected systems, caches and cues, different application servers, a database server that doesn't know how the application works. So mostly just gets and sets data. It doesn't participate in the reactive state graph. It doesn't take that much ownership over the whole system. The really non-trivial meta layer in historical backend engineering and distributed systems is consistency and race conditions. LLMs are really bad at consistency problems and race condition problems. And I think there are at least two reasons I can understand as to why. One is the thing we talked about last time, right? So the system that might be the place where the races are happening is some cache that there's two different systems all trying to update the cache to be um invalidated with respect to a change. Right? There's a there's a mutation A happening in one part of the codebase. There's a mutation B happening in one part of the codebase and there's a cache C which is a composition of A and B. And since these two different parts of the codebase change A and B, then it may be that when the two of them attempt to invalidate the cache which is in some other system which doesn't have a guaranteed like atomicity property, it's not atomic with respect to A being changed or B being changed in the underlying database. You can easily have like miss an update, right? where like A was changed um and B was changed, but you actually only reflected one of those two changes rather than the composition of both of them into the recomputed cache value C. When you've got all of these different servers owning these different things and they're not all in the same kind of transactional system, these kinds of problems happen all the time. So, the fact it is a separate system is related to that non-local thing we talked about recently. But you could say, well, why doesn't the LLM automatically produce architectures which are incapable of making this happen, right? This this is a big enough problem. Everybody knows these are problems. So why don't LLM generate code without race conditions? So they don't have to reason about non-local effects. Well, the strategies for doing it in open-ended systems are the combinatorial space is very large and it's doesn't show up in code. So it's not in the syntax, it's in the reasoning about the the the syntax. So there is a meta layer on top of code, especially in large systems that race conditions in particular and and loose consistency guarantees make extremely large in terms of the kinds of things you need to check or the order in which you do things or the way that you should shape code, if you're allowed to shape it any way to make two systems authored at very different times have a naturally consistent relationship to each other. the the the meta layer on top of our backend code about it is extremely high in traditional backends where there's no consistency relationship between all the parts. One thing I didn't show you if you scroll down to the summary about Opus' conclusions about our you know linear update right kind of problem is race conditions everywhere right so two mass markdown simultaneously your recalculation worker might read stale counts you need distributed locks or optimistic concurrency control by convex integrating all of these disperate pieces in fact all of these disperate pieces into one managed state graph where caching is automatic. You never have to manage it yourself. It automatically invalidates and consistency is strong across all of those components. You basically eliminate a whole meta layer on top of your code about race conditions and consistency that just somehow is not encapsulated into the training set in a way that LMS are able to act on. And it probably is some combination of a lot of the ways these things have been solved very specific to so many different kinds of like object level architectures. There's a lot of different metas about the consistency story. I also think that a lot of the solutions of those consistency problems happened at very big companies where how they solve them is not public. It doesn't make it into the kind of textbook sort and public blog knowledge set. So in conclusion, these software engineering tasks, why is why is convex work so well with LLMs? Why are LLM's good at writing convex? For a lot of the same reasons they're good at writing React and those reasons can be held in contrast to traditional distributed systems in a similar kind of way. jQuery and and React have a contrast. One is feedback, right? So everything in code uh everything in a type system um l you know react being just running in the browser that's the only environment there's no dashboard that controls your application state management behavior react is all code convict is all code react is all one language if you're using TypeScript it's all one type system feedback for agents which are imperfect just like humans when they have feedback they can fix their mistakes Second, convex's design is friendly to local reasoning. And local reasoning is very good because the context window is small. and any changes that have to do with outside systems that aren't the function that's being worked on right now, some other far-flung function somewhere else in the codebase that has a stateful assumption about a side effect of the code that the LM is changing, the LM will have no idea about that assumption. Um, and speaking of assumptions, um, minimizing meta convex does not have race conditions. it doesn't have lots of things that rely on LM being good at a rule set that's not embodied purely in code right so they um the automatic consistency cache management stuff like that means that um you know a lot of those skills that aren't in the training set about how to handle all possible race conditions however you would ever write down all those rules right LLMs don't know about that stuff and they don't have too. I hope that was interesting and uh gives you just a little bit more of an idea on the kinds of platforms that AI works really well with. Uh if you like that, please do all the things that you should do on a YouTube channel like subscribe and like and then turn on is there a bell? Can you turn on a bell? Turn on the bell. Thanks.
"Convex is agent-friendly." "It let me write code instead of worrying about SQL." "Agents are really good at writing Convex apps." That kind of comment keeps showing up, and it raises an obvious question: aren't agents supposed to be good at everything? If an LLM is meant to be an all-powerful developer, it shouldn't need a particular backend to write decent software. But LLMs aren't good at everything. Three specific things about Convex's design make agents succeed anyway, and they go a long way toward explaining why Convex agents work as well as they do. I'm Jamie Turner, Convex's CEO, and I'll walk through what those three are.
What LLMs are good at, and where they fall down
Start with what LLMs are actually good at. They're incredibly broad, far broader than any individual person could be. An LLM probably knows Vue better than I do, and it knows more about chemistry than most chemists know about web development. That breadth is real. Most of us just don't get much use out of it day to day, because most days we're working in one narrow domain. The fact that a model can also write competent Shakespearean poetry doesn't help me much when I'm building a web app.
Depth is a different story. Within a specific domain, picking the right best practice for the right problem, LLMs are weaker than true experts. That's part of why new engineers tend to overrate them and experienced engineers tend to underrate them. New engineers haven't yet built the pattern-matching that spots where a model's suggestion is subtly wrong. People outside a domain are more impressed by an LLM's competence in it than people inside it are, because outsiders can't see where it's cutting corners.
Speed is the real superpower, especially speed relative to cost. LLMs produce code far faster than a person can. That speed is useful even when breadth and depth aren't the deciding factor.
Then there's context, the biggest practical limitation of the bunch. If something is well-represented in the training data, LLMs are excellent at it. Once you get project-specific, meaning last-mile reasoning about a particular codebase, models are still much worse than strong engineers.
A good engineer carries a compressed mental model of a large codebase: which parts do which job, where to look when something needs to change, how a change in one place ripples through the rest. LLMs are much worse at building and using that kind of compressed artifact right now. That's a big part of why they're great at to-do apps and so much shakier on anything with real depth. A to-do app is a well-known pattern, it generates fast, and the context to build one is small enough that a model can hold all of it at once.
Why Convex, and not jQuery or classic backends
This context weakness explains an odd pattern. jQuery has been around far longer than Convex, with vastly more jQuery code in any model's training set. Even so, LLMs are worse at building working jQuery sites than at building Convex apps. The same holds for classic distributed backends: a constellation of application servers, caches, queues, and databases. Models can produce that kind of code, but it frequently doesn't work.
The comparison that actually explains this is React, not the raw amount of training data. React's central contribution to web development was composition. It's literally named after components, and that's the same problem Convex solves on the backend. Three specific parts of that design are what let Convex agents succeed where they struggle everywhere else.
Trick one: everything is code, so agents get real feedback
Agents are probabilistic. The gap between the best model and an average one is large, and even the best models get things wrong regularly. Types are one of the most effective feedback loops an agent has: change something, run it, read the type error, correct it, repeat.
In Convex, the schema, the HTTP routes, the background jobs, even agentic workflows installed as npm packages, are all defined in code. They live in the same codebase, sharing one type system all the way back to the database schema. When an agent generates something slightly wrong, it gets a type error telling it exactly what to fix. Once the compiler is satisfied, the project is usually close to correct.
Something like this, in a Convex app, is one continuous, typed path from database to function to client:
1// convex/schema.ts2exportdefaultdefineSchema({3 tasks:defineTable({4 title: v.string(),5 status: v.union(v.literal("todo"), v.literal("in_progress"), v.literal("done")),6}),7});89// convex/tasks.ts10exportconst setStatus =mutation({11 args:{ id: v.id("tasks"), status: v.union(v.literal("todo"), v.literal("in_progress"), v.literal("done"))},12handler:async(ctx,{ id, status })=>{13await ctx.db.patch(id,{ status });14},15});1617// In the client18const setStatus =useMutation(api.tasks.setStatus);19// TypeScript rejects a typo like status: "donee" before the agent ever runs the code20
Traditional backends don't offer that. A typical production setup scatters its configuration across surfaces that have nothing to do with each other:
What needs configuring
Where that config lives
HTTP traffic
An Nginx config file
Infrastructure
Terraform
Container orchestration
Kubernetes YAML
Queues
A web dashboard
Everything else
An assortment of AWS services
Each one has its own language and its own dashboard, and an agent has no clean way to read or manipulate most of them. Worse, some of it only matters in production, so the feedback an agent gets in development doesn't necessarily hold once the app ships.
In Convex, dev and prod work the same way, in the same language, with the same types. There's no gap between what an agent learns while iterating and what's true once the app is live.
A typical full-stack app also runs a different type system at every layer: client-side state, HTTP parameters, a backend language, an ORM or something like tRPC bridging to SQL types. Convex collapses all of that into one thing. Change a database type and the UI code shows a type error right away, and an agent sees that error the same way you would. Propagating a state change from the schema all the way down to the client, in full, is unusually complete in Convex compared to most stacks.
Convex is also starting to extend this feedback loop into runtime information. In a typical distributed system, no one, sometimes not even the original developers, fully understands how the cache, the queue, the app server, and the database relate to each other under load. Convex ingests the entire typed data flow, front end and back end together, so it can tell an agent exactly what's slow and why. Its execution is also largely deterministic, so it can replay production traffic against a proposed change and confirm it got faster without changing behavior. That capability is early, but it points at the same idea. Give the agent a real signal, and it can act on it.
Trick two: the backend is reactive, so agents can reason locally
Local reasoning is what composition actually buys you, and it fixes the worst weakness LLMs have: limited context. When local reasoning holds, everything an agent needs to make a correct change sits inside the one function or component it's already looking at.
The simplest React component, the one every tutorial starts with, takes a value and renders it. It doesn't know or care how that value gets set. It could be rendering millions of instances. It only has to guarantee that whatever value it's given, it renders correctly, and React re-runs it when the value changes. The code that updates that value, somewhere else entirely, doesn't need to know how many components are reading it either.
Producers don't need to know about consumers, and consumers don't need to know about producers. That's what lets people make small, local changes to huge React codebases without holding the whole thing in their head. It's also exactly what an LLM needs, because a model does best when it can look at one function, generate a type-correct transformation, and be done.
Convex extends that same guarantee to the backend, because the database itself is reactive. You can write a Convex function without tracking every other mutation in the app that might touch the same data. For a backend, that's genuinely unusual.
The problem this solves shows up clearly in a collaborative project-management tool, a Linear or an Asana. Move one task from in progress to done, and a cascade kicks off: the project's percent-complete bar updates, a teammate's contribution count changes, the sprint burndown redraws, a Slack notification fires, and the activity feed gets a new entry. In a traditional architecture, a client talks to an app server backed by a database, a cache, a queue, and background workers. That one change fans out into a lot of places that all have to remember to react correctly.
Add a new status like "abandoned" later, and every one of those dependent calculations has to be found and updated by hand. It's easy to miss one, a cache invalidation here, a notifier there. As a codebase grows, remembering every place with an implicit dependency on a piece of state gets hard for a person and much harder for a model with a small context window.
Traditional backend versus Convex
This is a big part of why LLMs struggle with jQuery specifically. jQuery gave you convenient, standardized DOM manipulation, but it never managed state dependencies for you. You were always on the hook for wiring up what should update when something changed. That meant tracking a graph of dependencies by hand, across a codebase nobody could fully hold in their head, human or model. React's compositional design fixed that for the frontend once codebases got big enough that human working memory started to fail. LLMs hit that same wall much sooner than people do, so a system that removes the manual tracking helps them sooner, and more.
Trick three: minimizing the meta layer around race conditions
The third piece is more abstract, but it has the clearest practical bite. You know how to add any two numbers because you understand the underlying rules, the meta layer for how addition works, not because you memorized every combination. LLMs pick up meta-layer knowledge the same way, from patterns that are well represented in training data. A model plays checkers well because the moves and the strategy around checkers are all over its training data. Hand it a simple game you invented five minutes ago, and it's often much worse, because there's no meta-layer knowledge about that game to draw on.
Traditional backend engineering carries a big, mostly-invisible meta layer around consistency and race conditions, and LLMs are bad at it for two related reasons. First, the relevant state is usually split across independent systems: a cache here, a database there, each with its own mutation path. If a change in one system needs to invalidate or update the other, and that isn't handled atomically, you can end up reflecting only one of the two updates. Second, the strategies for avoiding that live almost entirely in engineers' heads rather than in public code or docs: ordering guarantees, what to check before a write, how to structure code so independently-owned systems stay consistent. It's operational knowledge concentrated at a handful of large companies, not something that shows up in the training corpus the way a syntax pattern does.
Convex sidesteps most of this by collapsing the pieces into one managed state graph instead of a collection of independently-owned systems. Convex's transaction protocol uses optimistic concurrency control. A mutation reads a consistent snapshot, and if something else wrote to the same data before it commits, Convex retries the mutation automatically instead of letting the two writes interleave unpredictably. Caching and invalidation happen automatically and stay consistent with the underlying data, so there's no separate cache-invalidation logic for an agent to get wrong in the first place.
That removes more than bugs. It wipes out an entire category of meta-layer knowledge that LLMs were never going to reach reliably. A rule set that lives in senior engineers' heads and postmortems isn't one an LLM can learn from training data, no matter how good the model gets.
The throughline
All three come back to the same comparison. Convex is agent-friendly for close to the same reasons React was people-friendly, and for close to the same reasons jQuery and classic distributed backends aren't.
Feedback works because everything is code, typed end-to-end, with no separate dashboard or config language sitting outside that type system, the way there is with React in a browser. Local reasoning works because the backend is reactive the same way a React component is, so an agent working on one function doesn't have to model the whole rest of the app to get it right. And minimizing the meta layer around consistency and race conditions means agents aren't leaning on tacit, undocumented expertise that was never going to show up in their training data.
What all three tricks do is narrow the job. They strip out the categories of knowledge agents were always going to be weakest at: project-specific context, cross-system dependency tracking, and distributed-systems folklore. In their place, agents get the one thing they're genuinely strong at, writing type-correct code and reacting to feedback until it compiles. That's why Convex agents punch above their weight. It doesn't make them good at everything, and it was never going to.
All gas, no breakages
Convex is the reactive backend platform that keeps up with you and your agents. Database, functions, workflow, sync, search, file storage, and more. All TypeScript, zero glue.