Skip to content

275 bun optimized#498

Merged
antonputra merged 2 commits into
antonputra:mainfrom
solmanter:275-bun-optimized
Dec 21, 2025
Merged

275 bun optimized#498
antonputra merged 2 commits into
antonputra:mainfrom
solmanter:275-bun-optimized

Conversation

@solmanter
Copy link
Copy Markdown
Contributor

@solmanter solmanter commented Dec 20, 2025

Intro

Hi Anton! I watched your Go and Typescript comparison video (the latest one) and I want to improve on this code. I just updated bun to be more optimal. Thanks for your work!

Changes

  • Simplified user API routes in app.ts, ensuring proper response status codes.
  • Updated database connection string format in db.ts for PostgreSQL.
  • Enhanced user saving logic in users.ts to directly use the User object.
  • Changed config loading method in config.ts to use Bun's file API for better compatibility.
  • Removed error logging to be fair with go

- Simplified user API routes in app.ts, ensuring proper response status codes.
- Updated database connection string format in db.ts for PostgreSQL.
- Enhanced user saving logic in users.ts to directly use the User object.
- Changed config loading method in config.ts to use Bun's file API for better compatibility.
- Modified the build script in package.json to include the --sql-preconnect option for improved database connection handling.
- Refactored the save function in users.ts to destructure the user object, enhancing code readability and maintainability.
Copy link
Copy Markdown
Owner

@antonputra antonputra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I really appreciate your help. I'll definitely use it for my next benchmarks!

@antonputra antonputra merged commit c1d03bf into antonputra:main Dec 21, 2025
Copy link
Copy Markdown

@RiskyMH RiskyMH left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just some comments on how one could improve this further. I can make a pr if you'd like.

];
return Response.json(users);
}
if (path === "/healthz") return new Response("OK", { status: 200 });
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could easily be a Bun.serve routes property instead of in fetch() to be really static. The dynamic functions also too, because new URL is really expensive in JS and is doing a lot more than you need here

https://bun.com/docs/runtime/http/routing

For example code
const server = Bun.serve({
  routes: {
    "/healthz": new Response("OK", { status: 200 }),
    "/api/users": {
      GET: async request => {
        const users: User[] = [
          { id: 1, name: "David D. Patton", address: "1670 Stiles Street", phone: "412-578-3857", image: `user.png`, },
          { id: 2, name: "Gary E. Eaton", address: "828 Collins Avenue", phone: "614-866-1660", image: `user.png`, },
          { id: 3, name: "John J. Fox", address: "1895 Columbia Mine Road", phone: "304-505-3622", image: `user.png`, },
        ];
        return Response.json(users);
      },
      // or event simpler, but it feels like possibly cheating:
      GET: Response.json([
        { id: 1, name: "David D. Patton", address: "1670 Stiles Street", phone: "412-578-3857", image: `user.png`, },
        { id: 2, name: "Gary E. Eaton", address: "828 Collins Avenue", phone: "614-866-1660", image: `user.png`, },
        { id: 3, name: "John J. Fox", address: "1895 Columbia Mine Road", phone: "304-505-3622", image: `user.png`, },
      ] satisfies User[]),

      POST: async request => {
        const incomingUser = await request.json() as User;
        const datetime = new Date();

        const user: User = {
          name: incomingUser.name,
          address: incomingUser.address,
          phone: incomingUser.phone,
          image: `user-bun-${datetime.getTime()}.png`,
          createdAt: datetime,
          updatedAt: datetime,
        };

        try {
          const record = await save(user);
          user.id = record[0].id;
          return Response.json(user, { status: 201 });
        } catch (error: unknown) {
          return Response.json({ message: (error as Error).message }, { status: 400 });
        }
      },
    },
    "/*": new Response("Resource not found", { status: 404 }),
  },
});

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Static routing is indeed faster, but we keep it around because we aim to simulate real-world scenarios as closely as possible. and similar code structure like go

Copy link
Copy Markdown

@RiskyMH RiskyMH Dec 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For similar, we should at least use routes then (at very least don't use URL class)... but using actual static is pretty real world imo (its not like its a hidden feature of bun)

If your talking about the GET request for users, yeah that imo should be DB anyway

Comment thread lessons/275/bun-app/src/app.ts
Comment thread lessons/275/bun-app/src/config.ts
},
"scripts": {
"build": "bun build --compile --minify --sourcemap ./src/app.ts --outfile bun-app"
"build": "bun build --compile --minify --sourcemap --sql-preconnect ./src/app.ts --outfile bun-app"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

--sql-preconnect is for runtime not bun build, though I think we could do a --compile-exec-argv=--sql-preconnect type thing

But with how its set via config.yaml and not env vars, I can't see any way this is usable here

Copy link
Copy Markdown
Contributor Author

@solmanter solmanter Dec 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

your are right, that should on runtime

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like default behavior anyway, when you deploy an app, it creates all those connections immediately. The more interesting question is why, by the end of the test, it drops the number of connections.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is interesting to me, i can't find the reason in my tests and benchmarks. It always stayed the same

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All this pre connect does is start the connection before javascript code. Which means in theory faster... but as its not set in DATABASE_URL, this flag can't be used

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is incorrect for this build and it's not important because bun simply ignores this flag. Also, database connections somehow decreased during the bun benchmark. And it done before this update. That's the real problem.

Comment thread lessons/275/bun-app/src/db.ts
Comment thread lessons/275/bun-app/src/app.ts
@antonputra
Copy link
Copy Markdown
Owner

@RiskyMH Thank you for reviewing this!

@solmanter solmanter deleted the 275-bun-optimized branch April 26, 2026 18:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants