The ultimate beginner’s guide to Deno

Mayank Choubey
Tech Tonic
Published in
17 min readDec 27, 2021

--

The audience of this Deno 101 guide are people who are curious about Deno and want to get started with just enough basics. This is a beginner’s guide that helps to get started from scratch. Every section ends with links to additional resources that can help learn the topic in detail.

For further reading, the complete guide (index of 225+ articles) to Deno is located here.

TABLE OF CONTENTS

The ultimate beginner’s guide to Deno is divided in the following sections:

  • Introduction: What is Deno, main features, etc.
  • Exploring Deno: Installation, upgrade, REPL, hello world server, etc.
  • Commands: Basic commands
  • Sandboxing: Permissions & sandboxing
  • Modules: core, standard library, & third party modules
  • Hello world servers: Native, standard library, & Oak
  • Example applications: Content server, URL shortener, & ephemeral file server

Let’s get started!

INTRODUCTION

History

Deno is a simple, modern, and secure runtime for JavaScript and Typescript applications. It came almost 9 years after the first release of Node.js, a very popular runtime for server-side JavaScript applications. The Deno project is spearheaded by Ryan Dahl. Ryan is also the original creator of the extremely popular server-side runtime, Node.js. After the initial release of Node.js, he headed the Node.js project for the initial 3–4 years. Later on, the Node.js project got moved under NPM (Node Package Manager) & Ryan moved on to other things.

In 2018, Ryan made a comeback when he gave a famous talk about his regrets on Node.js. In that talk, he went over all the things he still regretted about Node.js. He ended up the talk announcing a new runtime called Deno. The regrets motivated him to create a new runtime from scratch. The ultimate goal was to create a new secure runtime, that is modern and addressess the mistakes that he did with Node.js. His major regrets were:

  • Promises: The core Node.js code is mostly callback based. Some core modules have recently moved to promises.
  • Access: A Node.js program can access everything that’s accessible by the user running it.
  • NPM: NPM is a very popular package manager, but privately controlled.
  • Node_modules: The module resolution is totally custom and complicated. No standards were followed.

Features of Deno

Deno is a simple, modern, and secure runtime for JavaScript and TypeScript applications. It supports Typescript out of the box. Deno is written in Rust, a modern systems programming language. Deno uses Google’s ultra-fast V8 engine to run the JavaScript code.

Here is the list of the top features of Deno:

  • Secure by default: Deno is secure by default. Unless enabled, there is no file, network, or environment access to the application. All the accesses need to be enabled explicitly. A Deno process doesn’t automatically inherit all the permissions that the running user has. All the accesses can be enabled globally or granularly. It is like running Deno in a container without having the overhead of a container runtime.
  • TypeScript out-of-the-box: Deno supports Typescript out of the box. Deno has built-in support for Typescript through the TSC/SWC compiler. It’s important to note that, Typescript code needs to get converted to JavaScript code before it can run on the V8 engine as V8 still doesn’t understand Typescript. Conversion from Typescript to JavaScript happens at startup, unless there are dynamic imports.
  • Single executable: Deno ships as a single executable. Although Deno is a single executable, it contains the entire development tool chain. The single executable includes: Core engine that runs TS/JS code, Tester, Upgrade manager, Debugger/Inspector, Formatter, Linter, Distributor, etc.
  • Third-party packages: Deno doesn’t require/support any package manager to host third-party packages. All the third-party packages can be used as standard ES modules which gets imported through HTTP or could also be local. They can be hosted anywhere like GitHub, enterprise web server, personal web server, or local file system. Deno downloads them in a cache before using them.
  • Standard library: Like all the major programming languages, Deno comes with a standard library that contains common peer-reviewed utilities like file, hash, HTTP, I/O, mime, WebSocket, log, date, time, UUID, crypto, hash, etc. Most of the standard library’s APIs are available through promises. There are hardly any old-style callbacks.
  • Web APIs: Deno continually enhances its support for web APIs. The familiar web APIs makes it easier for developers to write both front-end & server-side code. Some examples are- fetch, File, TextEncoder, TextDecoder, localStorage, sessionStorage, etc.

Releases

Deno was announced in 2018, and then it went into breakneck development for almost two years. The first version of Deno that came out in the summer of 2020 contained most of the tool chain as well. After almost two years of heavy development, the first public release of Deno happened on May 13, 2020. This was 1.0.0, a major milestone.

There has been 17 major Deno releases in last one and half years.

At the time of writing, the latest Deno release is: v1.17.1

That’s all about introduction! Let’s move on to the next section & explore Deno.

Here are some additional resources:

EXPLORING DENO

In this section, we’ll learn about:

  • First time installation of Deno
  • Upgrade
  • REPL
  • A simple hello world sever

Installation

The best way to install Deno on Mac or Linux is by downloading an installation script through curl & then executing the installer using shell. On Macs, the popular application manager brew can also be used for installation. Once Deno is installed, Deno itself provides a way to upgrade.

$ curl -fsSL https://deno.land/x/install/install.sh | sh
############################################################# 100.0%
Archive: /Users/mayankc/.deno/bin/deno.zip
inflating: /Users/mayankc/.deno/bin/deno
Deno was installed successfully to /Users/mayankc/.deno/bin/deno
Run 'deno --help' to get started

The installer simply downloads the latest version as a zipped executable from https://github.com/denoland/deno/releases/latest/download/ and unzips in the default directory $HOME/.deno/bin.

To install in a custom directory like /usr/local/bin, an environment variable DENO_INSTALL needs to be set to the root directory i.e. the parent directory of the bin directory:

$ export DENO_INSTALL=/usr/local
$ curl -fsSL https://deno.land/x/install/install.sh | sh
############################################################# 100.0%
Archive: /usr/local/bin/deno.zip
inflating: /usr/local/bin/deno
Deno was installed successfully to /usr/local/bin/deno
Run 'deno --help' to get started

The installed version can be checked by running deno -V command:

$ deno -V
deno 1.17.1

The installation & usage on windows will be covered in a separate article

Upgrade

Once Deno is installed, it takes care of upgrades via sub-command (we’ll go through sub-commands in the next section). To upgrade, there is no need to use curl/brew/powershell etc.

To upgrade to the latest version, the deno upgrade can be used:

$ deno -V
deno 1.17.0
$ deno upgrade
Looking up latest version
Found latest version 1.17.1
Checking https://github.com/denoland/deno/releases/download/v1.17.1/deno-aarch64-apple-darwin.zip
28.6 MiB / 28.6 MiB (100.0%)
Deno is upgrading to version 1.17.1
Archive: /var/folders/hx/0f6tcxq52f396vfq0c8xfszc0000gn/T/.tmpxC9lTG/deno.zip
inflating: deno
Upgraded successfully
$ deno -V
deno 1.17.1

By default, deno upgrade command installs the latest version. To use a specific version, deno upgrade — version <version-string> needs to be used:

$ deno upgrade --version 1.17.0
Checking https://github.com/denoland/deno/releases/download/v1.17.0/deno-aarch64-apple-darwin.zip
28.6 MiB / 28.6 MiB (100.0%)
Deno is upgrading to version 1.17.0
Archive: /var/folders/hx/0f6tcxq52f396vfq0c8xfszc0000gn/T/.tmpX9ek0d/deno.zip
inflating: deno
Upgraded successfully
$ deno -V
deno 1.17.0

Uninstall

There is no explicit uninstallation of Deno. As Deno comes as a single executable, the uninstallation procedure is all about removing that executable. This needs to be done manually (at the time of writing).

REPL

A REPL is an interactive shell provided by most of the languages/compilers/runtimes etc. A typical REPL takes user instructions, executes them, and prints the output.

Deno’s REPL can be started by simply running the deno command (no args required):

$ deno
Deno 1.17.1
exit using ctrl+d or close()
>

Deno’s REPL with tab completions can be used to quickly write & run a small piece of code. The REPL eliminates the need to write a code, save it, and then run it using deno run command. Let’s see some examples of using REPL:

> console.log("Hello world");
Hello world
undefined
> const s="Hello world".split(" ")[0];
undefined
> s
"Hello"
> const res=await fetch("https://deno.land/");
undefined
> res.status
200
> res.body
ReadableStream { locked: false }
> (await res.text()).length;
24439
> new TextDecoder().decode(new Uint8Array(5).fill(65));
"AAAAA"
> await Deno.readTextFile("/var/tmp/testdata/sample.txt");
"Learning Deno Is Fun!\n"
>

The REPL experience is typical of any other language, compiler, etc.

Hello World

Deno can run both local and remote applications. A remote application is one that is not (yet) present on the local system. Deno can run an application from a URL. Internally, the application is downloaded, compiled, and then executed.

Once Deno is successfully installed, a basic hello world server can be started by simply calling a remote script with deno run:

$  deno run --allow-net=:8000 https://raw.githubusercontent.com/mayankchoubey/deno-examples/main/deno_hello_world.ts

We’ll go through commands & permissions in the next 2 sections

The server can be tested using curl command:

$ curl http://localhost:8000
Hello world!

That’s all about the basic exploration of the Deno runtime. In the next section, we’ll go over the sub-commands in detail.

Here are some additional resources:

BASIC COMMANDS

Deno is not only a runtime, but a complete development tool chain. All the functionality is provided through sub-commands. The complete list of sub-commands is as follows:

  • bundle
  • cache
  • compile
  • completions
  • coverage
  • doc
  • eval
  • fmt
  • info
  • install
  • lsp
  • repl
  • run
  • test
  • types
  • uninstall
  • upgrade

We’ll go through some of the commonly used sub-commands like run, cache, fmt, test, & eval. We’ll also skip a couple of them that we’ve already seen: upgrade & repl.

Run

The run command is used to run a JavaScript/TypeScript application. At minimum, the run command needs two inputs:

  • An optional list of allowed permissions
  • the application to execute (aka main module)

We’ll go through permissions & sandboxing in the next section.

The typical format of deno run command is:

deno run <permissions> <path-to-app> <command-line-args-for-app>

For simplicity, let’s revisit the hello world program we’ve seen in earlier section:

//app.ts
import {serve} from "https://deno.land/std/http/mod.ts";
const handler=()=>new Response("Hello world!");
serve(handler, {port: Number(Deno.args[0])});
console.log("Server listening ...");

The simple application can be executed using deno run command as follows:

$ deno run --allow-net=:8000 app.ts 8000
Server listening ...

The above server can be tested using curl command:

$ curl http://localhost:8000
Hello world!

Cache

The cache command is used to download and compile the main application and all the dependencies. This is useful for production deployments where an application should only be started if all the dependencies can be loaded and compiled. The usage of cache command can reduce runtime errors.

$ deno cache app.ts 
Download https://deno.land/std/http/mod.ts
Warning Implicitly using latest version (0.119.0) for https://deno.land/std/http/mod.ts
Download https://deno.land/std@0.119.0/http/mod.ts
Download https://deno.land/std@0.119.0/http/cookie.ts
Download https://deno.land/std@0.119.0/http/http_status.ts
Download https://deno.land/std@0.119.0/http/server.ts
Download https://deno.land/std@0.119.0/async/mod.ts
Download https://deno.land/std@0.119.0/_util/assert.ts
Download https://deno.land/std@0.119.0/datetime/mod.ts
Download https://deno.land/std@0.119.0/async/deadline.ts
Download https://deno.land/std@0.119.0/async/debounce.ts
Download https://deno.land/std@0.119.0/async/deferred.ts
Download https://deno.land/std@0.119.0/async/delay.ts
Download https://deno.land/std@0.119.0/async/mux_async_iterator.ts
Download https://deno.land/std@0.119.0/async/pool.ts
Download https://deno.land/std@0.119.0/async/tee.ts
Download https://deno.land/std@0.119.0/datetime/formatter.ts
Download https://deno.land/std@0.119.0/datetime/tokenizer.ts
Check file:///Users/mayankc/Work/source/denoExamples/app.ts

Fmt

The fmt command is useful in formatting the source files as per the provided guidelines. At this point, the built-in formatter has a small number of customizations. By default the formatter uses:

  • Spaces instead of tab
  • Indentation width of 2
  • Max columns of 80
  • Double quotes instead of single quotes

The deno fmt command can be used with — check option to look at the suggestions. The same command can be repeated without — check to make changes in the source files. The formatter directly modifies the source files.

If all look good, the formatting suggestions can be accepted by omitting — check:

$ deno fmt app.ts 
/Users/mayankc/Work/source/denoExamples/app.ts
Checked 1 file

The formatted code looks like this:

import { serve } from "https://deno.land/std/http/mod.ts";const handler = () => new Response("Hello world!");
serve(handler, { port: Number(Deno.args[0]) });
console.log("Server listening ...");

Test

The test command can be used to run Deno’s built-in test runner. The test runner can be used to run unit, integration, or performance tests. The test runner works in two stages:

  • Register all the test functions using Deno.test API
  • Execute registered test functions & fail the tests that raises error

Let’s take a very simple example to unit test. Here is a simple module that we want to test:

//utils.ts
export async function randomId(n: number = 1) {
let ret = "";
for (let i = 0; i < n; i++) {
ret += await crypto.randomUUID().split("-").join("");
}
return ret;
}

For the above module, we’ll create a test file called util_test.ts. The test file would contain two simple tests:

//util_test.ts
import { assert } from "https://deno.land/std/testing/asserts.ts";
import { randomId } from "./util.ts";
Deno.test("no input", async () => {
const id = await randomId();
assert(id.length === 32);
});
Deno.test("n=10", async () => {
const id = await randomId(10);
assert(id.length === 32 * 10);
});

The deno test command can be used to run all the tests specified in a given file or all the file present in current directory that matches predefined names:

Eval

The eval command is generally useful in running a single line of code quickly. This is even shorter than going into REPL. The output of eval command can be printed on the console by using — p option.

$ deno eval "await Deno.readTextFile('/var/tmp/testdata/sample.txt')" -p
Learning Deno Is Fun!
$ deno eval "await crypto.randomUUID()" -p
c9094b9f-c485-44b1-816c-a73504dd2425

That’s all about the basic & commonly used commands. In the next section, we’ll learn about one of Deno’s primary feature: sandboxing.

Here are some additional resources:

SANDBOXING

One of the primary features of Deno is sandboxing. Deno runs in a strict sandbox and by default doesn’t inherit any of the access available to the user running the Deno command. This means that, unless explicitly enabled, there is no permission to:

  • File system
  • Network
  • Environment variables
  • Child process

This makes Deno secure by default. The sandbox is great, but not very useful for real-world applications till selective access is enabled. The access is enabled through a set of permissions. Let’s go over the permissions in detail.

If any kind of expected permission is missing, a PermissionDenied error is raised

File system

By default there is no access to the file system. The access can be enabled for:

  • Reading from file system for given paths or all the directories
  • Writing to file system for given paths or all the directories

A command-line option — allow-read and — allow-write can be used with run command to enable selective or full access:

//app.ts
const f=await Deno.readTextFile("/var/tmp/testdata/sample.txt");
console.log(f);

Let’s see the behavior with & without enabling sandbox (without any args, it becomes full access):

$ deno run app.ts 
error: Uncaught (in promise) PermissionDenied: Requires read access to "/var/tmp/testdata/sample.txt", run again with the --allow-read flag
$ deno run --allow-read=/var/tmp/testdata app.ts
Learning Deno Is Fun!
$ deno run --allow-read app.ts
Learning Deno Is Fun!

The same works for write permission:

//app.ts
await Deno.writeTextFile("/var/tmp/testdata/sample3.txt", "I am learning Deno\n");
$ deno run app.ts
error: Uncaught (in promise) PermissionDenied: Requires write access to "/var/tmp/testdata/sample3.txt", run again with the --allow-write flag
$ deno run --allow-write=/var/tmp/testdata app.ts
$ cat /var/tmp/testdata/sample3.txt
I am learning Deno
$

Network

By default, there is no access to network (or to open client & server sockets). The network access can be enabled to:

  • Open server sockets & accept incoming HTTP connections
  • Opening client sockets to make HTTP requests

A command line option — allow-net can be used with run command to enable selective or full network access:

//app.ts
import { serve } from "https://deno.land/std/http/mod.ts";
const handler = async () => {
const len = (await (await fetch("https://deno.land")).text()).length;
return new Response(len.toString());
};
serve(handler, { port: Number(Deno.args[0]) });
console.log("Server listening ...");

Let’s enable server socket access:

$ deno run app.ts 8000
Server listening ...
error: Uncaught (in promise) PermissionDenied: Requires net access to "0.0.0.0:8000", run again with the --allow-net flag
$ deno run --allow-net=:8000 app.ts 8000
Server listening ...

It doesn’t raise exception for fetch as that code hasn’t been executed yet. If we run a curl command, it’d raise a runtime exception:

$ deno run --allow-net=:8000 app.ts 8000
Server listening ...
PermissionDenied: Requires net access to "deno.land", run again with the --allow-net flag
$ curl http://localhost:8000
Internal Server Error

To enable client socket access, we need to include the domain deno.land in the allowed list:

$ deno run --allow-net=:8000,deno.land app.ts 8000
Server listening ...
$ curl http://localhost:8000
24439

Environment variables

By default there is no read access to any of the environment variables. Like earlier permissions, using command-line option — allow-env, the access can be enabled selectively to read some of the variables or read all of the variables:

//app.ts
const port = Deno.env.get('LISTENING_PORT') ||
Number(Deno.args[0]) ||
8000;
console.log(port);
$ deno run app.ts
error: Uncaught PermissionDenied: Requires env access to "LISTENING_PORT", run again with the --allow-env flag
$ export LISTENING_PORT=8080
$ deno run --allow-env=LISTENING_PORT app.ts
8080

Child process

By default, Deno application is not allowed to spawn a child process to run a shell command, another Deno process, an sub-process, etc. The — allow-run command-line option can be used to:

  • Selectively enable what commands can be executed
  • Allow all commands to execute
//app.ts
const td=(d:Uint8Array)=>new TextDecoder().decode(d);
const p=await Deno.run({
cmd: ['cat', '/var/tmp/testdata/sample.txt'],
stdout: 'piped',
stderr: 'piped'
});
console.log('STATUS:', await p.status());
console.log('STDOUT:', td(await p.output()).trim());
console.log('STDERR:', td(await p.stderrOutput()).trim());

Let’s test it out:

$ deno run app.ts 
error: Uncaught PermissionDenied: Requires run access to "cat", run again with the --allow-run flag
$ deno run --allow-run=cat app.ts
STATUS: { success: true, code: 0 }
STDOUT: Learning Deno Is Fun!
STDERR:

Here are some additional resources:

Modules

Modules provide complex functionality through simple APIs. They help in keeping the code short and relevant to specific business logic. By design, Deno doesn’t have & support a package manager (there is nothing like NPM). Instead, Deno supports downloading and importing packages/modules from anywhere: local or remote.

Deno support three sources for modules:

  • Core modules: These provide basic functionality & comes bundled with the core runtime
  • Standard library: These modules do not have external dependencies and they are reviewed by the Deno core team. The intention is to have a standard set of high quality code that all Deno projects can use fearlessly. There are published by the Deno team, but are not part of the core runtime.
  • Third-party: These modules are any third-party packages that are hosted anywhere in the world (GitHub, enterprise or personal web server, any CDN, etc.)

Let’s have look at each type.

Core modules

The core modules provide very basic level functionality like reading/writing files, HTTP client/server, create child process, etc. The core modules come bundled with the core runtime i.e. the standard Deno installation. The core module APIs are offered through the Deno namespace. It can be used direclty with Deno.<api-name>. There is no need to include anything to use the core APIs.

The complete list of all the core APIs is present here.

Here is an abbreviated list:

close, metrics, test, run, isatty, writeFileSync, writeFile, writeTextFileSync, writeTextFile, readTextFile, readTextFileSync, readFile, readFileSync, watchFs, chmodSync, chmod, chown, chownSync, copyFileSync, cwd, makeTempDirSync, makeTempDir, makeTempFileSync, makeTempFile, mkdirSync, mkdir, chdir, copyFile, readDirSync, readDir, readLinkSync, readLink, realPathSync, realPath, removeSync, remove, renameSync, rename, version, build, statSync, lstatSync, stat, lstat, truncateSync, …….. and so on

Let’s look at some examples:

Deno.args;
await Deno.readTextFile("/var/tmp/testdata/sample.txt");
await fetch("http://localhost:8000");
Deno.openSync("/var/tmp/testdata/sample.txt");
Deno.exit(1);

Standard library

Deno’s standard library’s modules do not have external dependencies. They are reviewed by the Deno core team. The purpose is to make a standard set of high quality modules that all Deno projects can use with trust. All the standard library modules can be seen here. Although standard library is published by Deno team, it is not a part of the core runtime. All the standard library modules needs explicit import.

Let’s have a look at some examples:

import { emptyDir } from "https://deno.land/std/fs/mod.ts";
await emptyDir("/var/tmp/testdata/someDir");
import {delay} from "https://deno.land/std/async/mod.ts";
await delay(5000);

Some of the core functionality like creating an HTTP server is provided by both Deno’s core and standard library. The only difference is that, the standard library’s API is much more simpler than the core API.

Third-party

The last category of modules are those that are not provided by Deno. The modules can be hosted anywhere. Deno’ll download the modules at application startup or if asked to cache explicitly. The third-party modules has two types:

  • Deno aware third-party packages: A large number of third-party packages are registered with Deno. They are made available through Deno’s URL rewriting service https://deno.land/x. Deno copies versions of these modules into it’s S3 buckets so that the modules are always available.
  • Other third-party packages: The remaining ones are any third-party packages that are hosted anywhere in the world (GitHub, enterprise or personal web server, any CDN, etc.).

Let’s look at examples of both:

import { getMachineId } from 'https://deno.land/x/machine_id/mod.ts'
console.log('My Machine ID: ', await getMachineId());
//DF47EE50-EDBB-5FA7-AAAA-DD330F898E0A
import {getRandomString} from "https://raw.githubusercontent.com/mayankchoubey/deno-random-id/main/mod.ts";
console.log(getRandomString(50));
//ea4849017656ad512ab9fcf328bbce900dc0cc89676b6d4d24

Here are some additional resources:

Hello world servers

In this section, we’ll write very basic hello world HTTP server in Deno. There are three common ways to go about it:

  • Using core APIs: Use the low-level core APIs to build an HTTP server with async iterators
  • Using standard library: Use standard library’s serve API to build an HTTP server with callbacks
  • Using third-party: Use popular frameworks like Oak, Abc to build an HTTP server with callbacks

Let’s take a brief look at each of the ways.

The core and standard library APIs use web standard Request and Response interface

Using core APIs

The lowest level of building an HTTP server is by using two of the lowest level APIs: listen and serveHttp. The listen API creates a TCP server and listens on the given address. The listen API returns an async iterable that yields a TCP connection in each iteration. The serveHttp API upgrades an incoming TCP connection by serving HTTP over it. The serveHttp API returns an async iterable that yields an HTTP Request in each iteration.

for await (const c of Deno.listen({ port: 8000 })) {
for await (const { request: req, respondWith: res } of Deno.serveHttp(c)) {
res(new Response("Hello world!"));
}
}

Let’s use curl to test it out:

$ deno run --allow-net=:8000 app.ts 
Server listening ...
$ curl http://localhost:8000
Hello world!

Using standard library

The standard library’s serve API can be used to write an HTTP server by providing two pieces of info: a callback handler and port number. Serve is one of the few APIs that uses callbacks. The serve API is a comination of listen and serveHttp APIs along with some error handling. The callback handler should can take a Request object as input and must produce a Response or Promise<Response>.

import { serve } from "https://deno.land/std/http/mod.ts";const handler = () => new Response("Hello world!");
serve(handler, { port: 8000 });
console.log("Server listening ...");

Let’s use curl to test it out:

$ deno run --allow-net=:8000 app.ts 
Server listening ...
$ curl http://localhost:8000
Hello world!

Using third-party

The popular third-party framework, Oak, comes with all the advanced functionalities like router, middlewares, auto body parsing, auto response building, etc. With Oak, there is no need for explicit request parsing and response building. The request object would be automatically parsed into context.request.body.value. To send a response, the JavaScript object/string/formData can be used directly in context.response.body.

import { Application } from "https://deno.land/x/oak/mod.ts";const app = new Application();
app.use(ctx => {
ctx.response.body = "Hello World!";
});
console.log("Server listening ...");
await app.listen({ port: 8000 });

Let’s test it out using curl:

$ deno run --allow-net=:8000 app.ts 
Server listening ...
$ curl http://localhost:8000
Hello world!

Example applications

In this section, we’ll point to three example Deno applications: content server, URL shortener service, and ephemeral file server.

Content server

A static content server is a fairly simple application. All it does is to get the file path from the request and sends the file back. Some content servers need authorization to access files, while others serve openly (public CDNs don’t use authorization).

Here are the links to the complete medium course on building content servers in Deno:

Here is the link to the GitHub repo of content server:

URL shortener

URL shortening is one of the commonly used web app. Shortening a URL & then redirecting the caller fully suits the async model of runtimes like Deno. This is because shortening & redirecting isn’t a CPU intensive operation.

Here are the links to the URL shortener resources:

Here is the link to the GitHub repo of URL shortener service:

Ephemeral file server

One of the well-known ephemeral file service is file.io. It supports secure uploading and downloading of files. The file is removed as soon as it gets downloaded.

Here are the links to the ephemeral file server resources:

Here is the link to the GitHub repo of ephemeral file service:

--

--