> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sevalla.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Deno

> This guide explains how to deploy a basic Deno site to Sevalla.

[Deno](https://deno.com/) is a modern, secure runtime for JavaScript and TypeScript. It is built with Rust and emphasizes security by requiring explicit permissions for file, network, or environment access. Deno supports TypeScript natively, includes a standard library, and utilizes URL-based module imports instead of a centralized package manager, providing a streamlined and secure alternative for server-side development and scripting.

Deno can only be used on Application Hosting; it cannot be deployed as a static site.

## Configuration

Deno runs TypeScript directly, eliminating the need for a separate build or installation step. With Sevalla:

* Dependencies are cached automatically on the first build.
* Your app can be started using `deno task start` or any custom start command you configure.

The following is an example `deno.json` file:

```javascript theme={null}
{
  "tasks": {
    "start": "deno run --allow-net --allow-env --allow-read src/index.ts"
  }
}
```

Ensure your start command includes all necessary **permission flags** for production:

* `--allow-net` - Enables network access (required for HTTP servers).
* `--allow-env` - Access to environment variables.
* `--allow-read` - File system read access (if needed).
* `--allow-write` - File system write access (if needed).

## Containerization

### Dockerfile

The build for [**Dockerfiles**](https://docs.sevalla.com/applications/build-options/dockerfile) is fully customizable. The following is an example Dockerfile for Deno:

```javascript theme={null}
FROM denoland/deno:latest

WORKDIR /app

COPY . .

RUN deno cache src/main.ts

EXPOSE 3000

ENV PORT=3000

CMD ["deno", "run", "--allow-net", "--allow-env", "src/main.ts"]
```

### Nixpacks

Nixpacks automatically detects Deno projects by looking for:

1. `deno.json` or `deno.jsonc` in the project root.
2. Deno imports in TypeScript files.
3. `deps.ts` file (common Deno convention).

Once detected, Nixpacks will:

* Install the latest Deno runtime.
* Cache dependencies from remote imports.
* Execute your start command as defined in `deno.json` .

For example, if you have a `deno.json` with a `start` task, as follows:

```javascript theme={null}
{
  "tasks": {
    "start": "deno run --allow-net --allow-env src/index.ts"
  }
}
```

Nixpacks will automatically install Deno and run `deno task start` to start your application.

#### Custom configuration with `nixpacks.toml`

You can customize the [**Nixpacks**](https://docs.sevalla.com/applications/build-options/nixpacks) build process by defining a `nixpacks.toml` file and using [**Nixpacks-specific environment variables**](https://nixpacks.com/docs/configuration/environment). This allows you to fine-tune how dependencies are installed, how your application is built, and which runtime settings are applied.

The following is an example `nixpacks.toml` configuration:

```javascript theme={null}
# nixpacks.toml

[phases.setup]
nixPkgs = ["deno"]

[phases.install]
# Cache dependencies by running a command that imports them
cmds = ["deno cache src/index.ts"]

[phases.build]
# Optional: Run build steps if needed
cmds = ["deno task build"]

[start]
cmd = "deno task start"
```

#### Common Nixpacks configurations

**Basic Deno application**

```javascript theme={null}
# nixpacks.toml
[phases.setup]
nixPkgs = ["deno"]

[start]
cmd = "deno run --allow-net --allow-env src/index.ts"
```

**Deno with specific version**

```javascript theme={null}
# nixpacks.toml
[phases.setup]
nixPkgs = ["deno"]

[phases.install]
cmds = ["deno upgrade --version 1.40.0"]

[start]
cmd = "deno task start"
```

**Deno with additional system dependencies**

```javascript theme={null}
# nixpacks.toml
[phases.setup]
# Add additional system packages if needed (e.g., for image processing)
nixPkgs = ["deno", "imagemagick", "ffmpeg"]

[phases.install]
cmds = ["deno cache src/index.ts"]

[start]
cmd = "deno task start"
```

**Monorepo with custom build path**

```javascript theme={null}
# nixpacks.toml (in monorepo root)
[phases.setup]
nixPkgs = ["deno"]

[phases.install]
cmds = ["cd apps/api && deno cache src/index.ts"]

[start]
cmd = "cd apps/api && deno task start"
```

**Deno with environment-specific builds**

```javascript theme={null}
# nixpacks.toml
[phases.setup]
nixPkgs = ["deno"]

[phases.build]
# Generate static files or run build tasks
cmds = [
  "deno task build",
  "deno run --allow-read --allow-write scripts/generate-config.ts"
]

[start]
cmd = "deno task start"
```

For more information about Nixpacks with Deno, refer to the [Nixpacks Deno documentation](https://nixpacks.com/docs/providers/deno).

## CDN

Sevalla provides a premium, Cloudflare-powered CDN for Application Hosting at no additional cost. To get the most out of Sevalla’s CDN when deploying your Deno application, we recommend the following best practices:

* [**Enable the CDN**](https://docs.sevalla.com/applications/cdn) for all production applications.
* Set appropriate `Cache-Control` headers on API routes to ensure proper caching behavior.
* [**Purge the CDN cache**](https://docs.sevalla.com/applications/cdn#clear-the-cdn-cache) after deploying critical updates to avoid serving stale content.
* Use versioned URLs for static assets, for example `/static/app.v123.js`.

### Optimizing Deno for CDN

#### Static files with cache headers

```javascript theme={null}
// src/index.ts
import { serveFile } from "https://deno.land/std@0.208.0/http/file_server.ts";

Deno.serve({ port: Number(Deno.env.get("PORT") || "3000") }, async (req) => {
  const url = new URL(req.url);

  // Serve static assets with caching
  if (url.pathname.startsWith("/static/")) {
    try {
      const filePath = `./public${url.pathname}`;
      const response = await serveFile(req, filePath);

      response.headers.set(
        "Cache-Control",
        "public, max-age=31536000, immutable"
      );
      return response;
    } catch {
      return new Response("Not Found", { status: 404 });
    }
  }

  // API endpoint with shorter cache
  if (url.pathname === "/api/data") {
    const data = { message: "Hello from Deno!" };

    return new Response(JSON.stringify(data), {
      headers: {
        "Content-Type": "application/json",
        "Cache-Control": "public, max-age=3600, s-maxage=3600",
      },
    });
  }

  return new Response("Not Found", { status: 404 });
});
```

## Edge caching

[**Edge caching**](https://docs.sevalla.com/applications/edge-caching) stores your Sevalla site cache on Cloudflare’s 260+ global data centers, delivering responses from the location nearest to each visitor for faster performance. To maximize the benefits of Sevalla’s Edge Caching for your Deno application, we recommend the following best practices:

* Set appropriate `Cache-Control` headers in loaders to control caching behavior.
* Combine edge caching with the CDN for a complete caching strategy.

### Optimizing Deno for edge caching

```javascript theme={null}
// src/index.ts
Deno.serve({ port: Number(Deno.env.get("PORT") || "3000") }, (req) => {
  const url = new URL(req.url);

  // API with edge caching
  if (url.pathname === "/api/products") {
    const products = getProducts(); // Your data fetching logic

    return new Response(JSON.stringify(products), {
      headers: {
        "Content-Type": "application/json",
        "Cache-Control": "public, max-age=60, s-maxage=3600",
      },
    });
  }

  // User-specific data (don't cache)
  if (url.pathname === "/api/user/profile") {
    return new Response(JSON.stringify({ user: "data" }), {
      headers: {
        "Content-Type": "application/json",
        "Cache-Control": "private, no-cache",
      },
    });
  }

  return new Response("Not Found", { status: 404 });
});
```

#### `Cache-Control`

With Sevalla’s Cloudflare integration, `Cache-Control` headers are respected at the edge, giving you precise control over how content is cached and served globally. The following are some common directives you can use in your Deno application:

* `public, s-maxage=3600` - Caches the response on the CDN for 1 hour, improving performance for frequently accessed content.
* `public, max-age=31536000, immutable` - Ideal for versioned static assets, allowing them to be cached for up to 1 year with no revalidation.
* `private` - Prevents CDN caching and ensures the response is only cached by the end user’s browser, for personalized or sensitive data.

<Info>
  Sevalla does not yet support the `stale-while-revalidate` Cache-Control directive. To prevent unexpected caching behavior, we recommend not using this directive in your API or asset caching settings.
</Info>

## Health checks

Ensure your application remains available during deployments by implementing health checks:

* Always implement [**health checks**](https://docs.sevalla.com/applications/processes#health-checks) for production applications.
* Keep checks lightweight; responses should complete in under 1 second.
* Verify critical dependencies (e.g., databases, Redis) as part of the checks.
* Return 200 for degraded states to allow deployments to continue smoothly.
* Return 503 only for critical failures that require pod restarts.

### Basic health check

```javascript theme={null}
// src/index.ts
Deno.serve({ port: Number(Deno.env.get("PORT") || "3000") }, (req) => {
  const url = new URL(req.url);

  if (url.pathname === "/api/health") {
    return new Response(
      JSON.stringify({
        status: "ok",
        timestamp: new Date().toISOString(),
        runtime: "Deno",
        version: Deno.version.deno,
      }),
      {
        headers: { "Content-Type": "application/json" },
      }
    );
  }

  return new Response("Not Found", { status: 404 });
});
```

## Graceful shutdown

Deno supports graceful shutdown signals. For custom cleanup logic, such as closing database connections, use `SIGTERM` and `SIGINT`, for example:

```javascript theme={null}
// src/index.ts
import { pool } from "./lib/db.ts";

const abortController = new AbortController();

Deno.serve(
  {
    port: Number(Deno.env.get("PORT") || "3000"),
    signal: abortController.signal,
  },
  (req) => {
    // ... your routes
  }
);

// Graceful shutdown
Deno.addSignalListener("SIGTERM", async () => {
  console.log("Received SIGTERM, closing connections...");

  // Close database pool
  await pool.end();

  // Stop server
  abortController.abort();

  console.log("Server closed gracefully");
  Deno.exit(0);
});

Deno.addSignalListener("SIGINT", async () => {
  console.log("Received SIGINT, closing connections...");
  await pool.end();
  abortController.abort();
  Deno.exit(0);
});
```

## S3

You can integrate your Deno application with S3 (Sevalla S3, AWS S3, or any S3-compatible storage) using the AWS SDK or JavaScript v3.

### Setup

1. **Install dependencies** (auto-cached on first run):

```javascript theme={null}
import {
  S3Client,
  ListBucketsCommand,
  PutObjectCommand,
  GetObjectCommand,
  DeleteObjectCommand,
} from "npm:@aws-sdk/client-s3@^3.400.0";
```

2. **Configure environment variables**:

```javascript theme={null}
S3_REGION=us-east-1
S3_ENDPOINT=https://s3.sevalla.com  # Optional: for S3-compatible services
S3_ACCESS_KEY_ID=your_access_key_here
S3_SECRET_ACCESS_KEY=your_secret_key_here
```
