{"slug":"why-tako-ships-an-sdk","url":"https://tako.sh/blog/why-tako-ships-an-sdk/","canonical":"https://tako.sh/blog/why-tako-ships-an-sdk/","title":"Why Tako Ships an SDK","date":"2026-04-04T12:00","description":"Most deploy tools stop at infrastructure. Tako's SDK gives your app readiness signaling, secret injection, and runtime abstraction — here's why.","author":null,"image":"c4e0bec69aac","imageAlt":null,"headings":[{"depth":2,"slug":"what-the-sdk-actually-does","text":"What the SDK Actually Does"},{"depth":2,"slug":"the-readiness-problem","text":"The Readiness Problem"},{"depth":2,"slug":"secrets-that-dont-leak","text":"Secrets That Don’t Leak"},{"depth":2,"slug":"same-code-dev-and-prod","text":"Same Code, Dev and Prod"},{"depth":2,"slug":"the-real-reason-what-comes-next","text":"The Real Reason: What Comes Next"},{"depth":2,"slug":"a-thin-layer-not-a-framework","text":"A Thin Layer, Not a Framework"}],"markdown":"Most deploy tools are infrastructure-only. They move your code to a server, maybe configure a reverse proxy, and call it a day. What happens inside your app process is your problem.\n\nWe think that's leaving a lot on the table.\n\nTako ships an SDK — [`tako.sh`](https://www.npmjs.com/package/tako.sh) for JavaScript/TypeScript, [`tako.sh`](https://pkg.go.dev/tako.sh) for Go — because the interesting problems in deployment happen at the boundary between infrastructure and application code. Readiness signaling, secret injection, health checks, graceful shutdown. These aren't app concerns or infra concerns. They're both.\n\n## What the SDK Actually Does\n\nThe SDK is thin. Your app exports a [fetch handler](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API), and the SDK turns it into a running server:\n\n```typescript\n// index.ts — that's it, that's your app\nexport default function fetch(request: Request): Response {\n  return new Response(\"Hello from Tako\");\n}\n```\n\nUnder the hood, the SDK handles everything between your code and the infrastructure:\n\n| Concern             | Without SDK                                   | With Tako SDK                                                 |\n| ------------------- | --------------------------------------------- | ------------------------------------------------------------- |\n| Server binding      | You configure host/port, pick a framework     | SDK binds to an OS-assigned port automatically                |\n| Readiness signal    | Infra polls a TCP port and hopes for the best | App signals `TAKO:READY` when _actually_ ready                |\n| Health checks       | You build a `/health` endpoint                | Built-in `/status` endpoint with uptime, version, instance ID |\n| Secrets             | `.env` files or external secret managers      | Injected via fd 3 before your code runs, auto-redacted on log |\n| Graceful shutdown   | You handle `SIGTERM` yourself                 | SDK drains in-flight requests, then exits cleanly             |\n| Runtime portability | Locked to one runtime's HTTP API              | Same `fetch()` signature across Bun and Node                  |\n\n## The Readiness Problem\n\nThis is the big one. Most deploy tools check health by poking a TCP port — if the socket accepts connections, the app must be ready. But that's not true. Your server might be listening while still loading config, warming caches, or running migrations.\n\nTako's approach is different. The SDK signals readiness explicitly:\n\n```d2\ndirection: down\n\nserver: tako-server\nlb: Load Balancer\n\napp: App + SDK {\n  startup: SDK startup {\n    secrets: Read secrets from fd 3\n    code: Import user code\n    bind: Bind to port\n\n    secrets -> code -> bind\n  }\n}\n\nserver -> app.startup.secrets: spawn (PORT=0)\napp.startup.bind -> server: \"TAKO:READY:12345\"\nserver -> app: probe /status\nserver -> lb: add instance\nlb -> app: route traffic\n```\n\nThe new instance writes `TAKO:READY:<port>` to stdout only after it has read secrets, imported your code, and bound to a port. The server waits for that signal, runs a health probe, and only then adds the instance to the [load balancer](/docs/deployment). No dropped requests, no 502s.\n\n## Secrets That Don't Leak\n\nSecrets deserve special mention. Tako encrypts secrets with AES-256-GCM and [stores them in your repo](/docs/cli). At deploy time, the server passes them to your app through file descriptor 3 — not environment variables, not files on disk.\n\nThe SDK reads fd 3 _before importing your code_, then exposes secrets through a `Proxy` that redacts itself. `tako typegen` emits a project-local `tako.gen.ts` with a typed `secrets` export:\n\n```typescript\nimport { secrets } from \"../tako.gen\";\n\nsecrets.DATABASE_URL; // → \"postgres://...\"\nconsole.log(secrets); // → \"[REDACTED]\"\nJSON.stringify(secrets); // → \"\\\"[REDACTED]\\\"\"\n```\n\nAccidental logging? Handled. Serialization into error reports? Handled.\n\n## Same Code, Dev and Prod\n\nOne of the quieter benefits: [`tako dev`](/docs/development) runs your app through the exact same SDK entrypoint as production. Same fetch handler wrapping, same readiness protocol, same health endpoint. The only differences are the ones you'd expect — local HTTPS on `.test` instead of your production domain, debug log level by default.\n\nThis means if your app starts correctly in dev, it starts correctly in production. No \"works on my machine\" surprises from a different server setup.\n\n## The Real Reason: What Comes Next\n\nEverything above is useful today. But the deeper reason we ship an SDK is what it unlocks tomorrow.\n\nWithout an SDK, a deploy tool can only manage processes from the outside — start, stop, route traffic. It has no way to coordinate with your application code. That's fine for basic deploys, but it's a dead end for anything more interesting.\n\nWith an SDK, we can add runtime capabilities that are type-safe, integrated, and impossible to bolt on from the outside:\n\n- **Background jobs** — define a job handler in your code, trigger it from any request, let Tako manage the queue and retries server-side. No external job queue to run.\n- **Durable workflows** — long-running, resumable workflows where Tako persists state across steps. Your code defines the steps, the SDK handles checkpointing and recovery.\n- **Scheduled tasks** — cron-like tasks declared in code, executed by the server. Type-safe, version-deployed, no separate cron service.\n- **Durable channels** — persistent WebSocket and SSE connections managed by the proxy, surviving deploys and instance restarts. The SDK handles connection lifecycle, reconnection, and message routing.\n\nEach of these features needs both sides of the equation: server-side infrastructure _and_ application-level integration. A deploy tool without an SDK would need you to bring your own job queue, your own workflow engine, your own scheduler. The SDK is what lets Tako offer these as built-in primitives — type-safe, zero-config, and deployed alongside your app.\n\nThis is where Tako is headed. The SDK is small today because we're building the foundation carefully. But it's the surface area that will grow the most.\n\n## A Thin Layer, Not a Framework\n\nThe SDK is not a framework. It doesn't have a router, an ORM, or opinions about how you structure your app. It's a ~200-line bridge between your fetch handler and Tako's infrastructure. You can use any framework you want — [Hono](https://hono.dev), [Elysia](https://elysiajs.com), Express, or just raw `Request`/`Response`.\n\nThe entire public API is one type (`FetchHandler`) and one class (`Tako`) with a handful of static methods. If you ever want to leave Tako, removing the SDK is a one-line change — export your fetch handler differently and bring your own server.\n\nWe think the best infrastructure is the kind that knows just enough about your app to do its job well — and nothing more. That's why Tako ships an SDK.\n\nCheck out the [docs](/docs) to get started, or read more about [how Tako works](/docs/how-tako-works) under the hood."}