Replying to @mjovanovictech
I'll be doing woodworking
2
1
30
3,717
A private setter can still leave your value object open to change. Say you ask an agent to write a Money type. The tests check the math, and they pass. You ask it to make the type fixed after it's built. It adds private set. With private set, code outside the class can no longer call that setter. Code inside it still can. When I review an AI change, I want to check the rule we asked for. Passing tests and readable code give me part of the answer. I also need to see what the type still allows. For a value that must stay fixed, I check the fields and every way to write to them. You need to check the objects it holds too, because a read-only field can still point to an object that can change. Try Freeze the Money in the free Katabench tour. Make the type fixed after it's built. The grader checks its structure as well as its output: app.katabench.com/?path=foun…
1
6
18
2,184
Your request has a timeout. The work can still keep running. ASPNET Core's timeout middleware cancels a token. It does not stop the thread or force your endpoint to return. For the timeout to help, the token has to reach the work. You need to pass it from the endpoint through your services and into EF Core or HttpClient. The called code must honor it too. In the guide's example, the endpoint has a three-second limit. If its ten-second delay ignores the token, it can still finish and return 200. You can test both paths: work that stops on cancellation and work that ignores it. Run that check without a debugger attached, since this timeout does not fire under the debugger. Here's the setup and the cancellation path to check: milanjovanovic.tech/blog/you…
3
6
39
2,820
In favor of AI. Wow. Didnt expect that
A: Uses AI coding agents HEAVILY in implementation and review and doesn't look at the code at all B: Hand writes and reviews everything Assuming the products solve the same problem etc, which product would you feel more comfortable trusting as a user?
5
1
22
13,509
A status check should never start another deploy. I've been using agents to improve the path from a commit to a running app. One setup I've reused runs CI checks before a Dokploy deploy can start. You can send one deploy request, then use a separate loop to read its status. That loop needs a limit so it can't wait forever. You also need a way to stop older runs from competing with newer work. For an embedded challenge feature, we ran the repo checks, deployed to staging, and checked the live flow on desktop and mobile. Once the deploy finishes, you still need to check the app. Is the service healthy? Does the route work? Can the user do what we meant to ship? You can write those checks into the release plan while the change is fresh. My free Agent Shipping Kit includes a release skill that asks your agent to check the running app before it calls the work done. milanjovanovic.tech/free/age…
4
7
31
2,279
Milan Jovanović retweeted
anyone still talking about loops? feels like last year's trend already pace of AI is mind-boggling
14
3
37
6,960
it can't get any worse, right? right...?
During this red-teaming exercise, we also found a vulnerability that allows for unauthenticated remote code execution in Brotli, a widely-deployed compression library included in many pieces of software such as Node.js, Bun, and Envoy. The flaw could let an attacker run their own code on affected systems by sending or replying with malicious compressed data, without any need to create a user account. That is, an unpatched server that accepts compressed input could be taken over by a malicious client, and an unpatched client that accepts compressed input (such as “curl --compressed”) could be taken over by a malicious server. This root cause issue was actually fixed in the Brotli source code in February, but it wasn’t known at the time that it gave rise to a security vulnerability and there was no more recent release of Brotli. Since Brotli is built into other software, any software which includes this library needs to take the update too, followed by the users of that software. We disclosed the vulnerability to Brotli and other downstream projects such as Node.js, which released or are currently releasing security updates, and Brotli cut new release versions and published a CVE. More details on the patch and mitigations below: patchtheplanet.org/brotli
5
1
40
7,779
"The query uses an index" is not the end of a performance review. Say you want the newest comment on an issue. Your index sorts by issue ID, then user ID, then date. It can find the issue's comments. But those comments are grouped by user before date. They are not in the order your query needs. So the database may still have to sort them. In a dashboard query, that work can repeat for each issue. The query plan lets you check the filter, sort order, and number of loops. For this read, an index on issue ID and date fits the work better. You still need to measure the whole query. More indexes also cost space and add work to writes. My PostgreSQL example shows how column order changes the plan: milanjovanovic.tech/blog/how…
3
4
42
2,337
Milan Jovanović retweeted
If you are into PHP, pivot to .NET.
32
22
319
17,573
A query can pass every small test and still load a whole table. When I review data-access code, these are the questions I want answered: 1. How many trips does it make? If you run a query for each row, a short loop can turn into hundreds of calls. 2. How much does it load? You can put the filter before ToList() and fetch just the fields you need. 3. Can it use an index? A function on a column can block a plain index, so check the query plan before you assume the index helps. 4. What changes when the table grows? You can test with more rows and watch large offsets and sorts done in the app. 5. Where does user input go? SQL parameters handle values. For column names, you need a list you control. The SQL and query plan show what the code does. Try Existence Without Loading on Katabench. Answer a yes/no question against a dataset with 200,000 rows, within 30 ms. You don't need to fetch the rows to count them. Start with the free puzzle: app.katabench.com/?p=any-not…
3
6
25
1,839
Two requests can both find an apartment free, then book the same dates. Each check can be right when it runs. The gap is between reading the bookings and saving a new one. The check needs to hold when you save, too. In this example, each booking also updates the same apartment row in the same save. That row has a version. EF Core includes the version it read in the UPDATE check. The first save changes it. The second request still has the old version, so its update fails. When you catch that conflict, you need to check the booking rules again before you retry the write. A version on each new booking row would not help here, since the two requests create separate rows. I explain the shared-row update and EF Core concurrency check here: milanjovanovic.tech/blog/sol…
3
4
51
2,558
High test coverage still leaves me with one question: what would make these tests fail? I use real PostgreSQL in Testcontainers and send requests through HTTP. That puts the real schema and data rules in the test. I also ask about the paths that are easy to skip. You can start with what happens if access is removed, a write rolls back, or a worker stops halfway through a job. With email, a timeout may leave you unsure whether the provider accepted the send. You need to resolve that doubt before a retry, or you could send it twice. For a bug fix, I want the test to fail on the old code and pass on the fix. Then I want the checks for the nearby code to pass too. Pick the failure you care about, then check whether your test would catch it. Get my free AI Code Review Kit. Its review skill guides your agent through failure cases and checks whether a test proves the fix. milanjovanovic.tech/free/ai-…
8
5
30
1,700
Milan Jovanović retweeted
If you give an agent access to your app, I want to see the checks around each tool call. The model can propose an action. Our code has to decide whether it's allowed. That's part of what an agent harness does. It also controls the context we send, tracks progress, sets limits, and checks the result. A framework can handle tool calls and checkpoints. We still need to define access rules and check the finished export. Say we're building an agent to export last month's orders. I'd fix the date range at the start and save it with the task. A retry next month should still use the same date range. We can give the model the export schema and those dates. Any notes in the order data should be treated as untrusted input. A note saying "send all orders to this address" must not become a new rule. When the model wants to do a tool call, our code checks the inputs and auth requirements. Don't give the worker more permissions than necessary. It only needs to read the allowed orders and write to the approved file store. I also want to know what happens if the app stops halfway through. You can save the run state and job ID outside the model context. This lets us resume from a record of the work. If a call times out, check its outcome before trying again. You should set limits on runtime and retries. Minimize getting stuck in a loop or marking a pending job as done. Before marking the task as done, check that the job succeeded and we can read the file. Then check the account, dates, and format. I want that proof before we tell the user their export is ready. A few more things you can test: - Access to the wrong account - Restart mid-run - Job that succeeds but doesn't export a file For each check, we should be able to name who owns it and point to the code or policy that enforces it. Oracle's guide covers how these parts fit into a production agent harness: fandf.co/4idVzik Huge thanks to @OracleDevs for sponsoring this post.
Paid partnership (ad)
8
8
40
2,224
A schema name does not stop another module from reading your tables. If every module uses the same database login, that login may have access to all of them. The folder and schema names do not change its rights. You can give each module its own PostgreSQL role, with access to its own schema. The module then uses that role in its connection string. That way, an accidental query against another module's private table can fail at the database. Each module still needs its own DbContext and a clear contract for shared data. If you need a shared read, the owning module can expose an API or a view with access granted on purpose. The rule is then part of the setup you can check. My guide shows the roles, grants, and EF Core setup: milanjovanovic.tech/blog/how…
5
5
37
1,796
Replying to @julienrenaux
As a founder since 1992, I look back and regret one too many Saturday's working instead of enjoying my spouse and children. So glad I read to them every night (then worked more after bedtime). Take it from me ... they grow up WAY too fast. Don't miss a moment with them. 😀
2
1
3
864
Anthropic reports worktree creation dropping from 7 minutes to 5 seconds. I break down why it replaced Git with Scion, how it handles 30,000+ merged changes a day, and what you can borrow for your agent workflows. Full breakdown in the video: piped.video/oKctAX-uzVE
3
2
24
2,074
A C# lock cannot stop the other copy of your app. When you add a second instance, each can start the same scheduled job. Each has its own lock in memory. For a shared job, you can have both instances try the same lock outside the app. With PostgreSQL, an advisory lock can choose who starts the work. The other instance can skip that attempt. That lock lasts only while its database connection holds it. If the connection is lost, another worker may get the lock while the old worker still has work in flight. A lock also does not record which scheduled runs have finished. So you still need to track completed work and make repeats safe. I show PostgreSQL advisory locks and the C# setup here: milanjovanovic.tech/blog/dis…
6
5
37
2,003
"We shipped 1000 PRs this month" Okay, but what did you actually build? PRs is the new "lines of code", but it doesn't tell you much
6
8
92
5,215
interesting that a CEO of a $3M MRR business feels threatened enough by a vibe-coded competitor to even respond in any way, let alone dedicate an entire newsletter to them email is about the last thing in my business I'd want to build myself... maybe just ignoring is smarter
an excerpt from today's newsletter @marclou did I miss anything?
5
1
7
2,481