So here’s a secret — SilverBullet is really just a Trojan horse to test a potentially much more widely applicable idea, the idea to make applications extensible at different levels of its stack in a controlled manner.
While they can perform arbitrary computations, they do have constraints:
- Stateless: while the runtime may keep functions running and reuse an instance to perform multiple invocations, functions have to be written without this assumption. Therefore any state needs to be maintained outside of the function.
- Self contained: they typically make limited assumptions on the environment other than a language runtime.
- Short lived: the assumption is that functions run for a limited amount of time, usually a few milliseconds, perhaps seconds, but a minute at most.
What can these functions do? In principle, anything, while being limited to access to the host. They generally cannot write to the host’s filesystem, for instance. They also tend to be constrained in allocated run time and memory. All communication with the outside world tends to happenThen, you configure when it should be triggered. This concept is not only interesting in terms of scalability — such a function can quickly scale to millions of invocations per second when necessary, and down to zero when that demand vanishes — but also in terms of portability. Couldn’t such functions conceptually run everywhere? And indeed, recently such functions have been moving to what’s called “the edge” as well, such as Lambda@Edge, Vercel’s Edge Functions, or Netlify’s Edge Functions. What is the “edge” here? Generally, the closest data center these providers offer near the user. The goal? Lower latency.But is that as edgy as we can get? What about the real edge: the user’s device?
- They have to be stateless: while the runtime may keep functions running and reuse an instance to perform multiple invocations, they cannot assume this is the case. They have to assume that every invocation happens in a fresh environment.
- They have limited access to the host machine, such as no direct access to a (persistent) file system.
- Hooks: are application-specific extension points. They can range from defining new commands to timer-based hooks (cron-like) to defining HTTP endpoints.
- Syscalls: expose (often) application-specific functionality to functions, allowing it to e.g. manipulate the UI, access various data stores, etc.
- Manifests: wire the whole thing together. They are YAML files that define the functions and what they hook into.
- Sandbox: each plug is run in its own sandbox. In the browser this is a Web Worker. On the server as well (although Deno enables deeper sandboxing than the browser). Sandboxes can, in principle, be flushed out and restarted at any time. In fact, this is how hot reloading of plugs is implemented.