Workers-specific constraints
Upstream Misskey is designed around a long-running Node.js process. That assumption does not hold on Cloudflare Workers, so the design changes to fit the constraints below.
Execution model
| Constraint | Effect | Approach |
|---|---|---|
| No long-running process; many execution environments (isolates) run side by side and can be discarded at any time | In-memory state cannot be shared or kept | State that must be shared lives in Durable Objects, KV, or PostgreSQL |
| No pub/sub between processes | Caches cannot be invalidated immediately | Rarely changing data (meta, roles) is kept with a short lifetime. Other execution environments see changes up to 30 seconds later |
| Accumulating deltas in memory and flushing them periodically does not work | Upstream's chart recording cannot be used | Charts are computed from the source data on request. IDs carry the creation time, so no extra recording is needed. Decrements and event-based series cannot be recorded |
| CPU time and subrequests per invocation are capped | Large jobs cannot run in one go | Account deletion, imports, account migration and similar jobs are split into small steps, each re-enqueuing the next |
| 128 MB of memory | Large files and outputs cannot be handled at once | The upload limit defaults to 100 MB. Exports of extremely large accounts can hit the limit |
| Machine information (CPU, memory, disk) is unavailable | Server info cannot be reported | Same shape as upstream, with fixed values |
Asynchronous processing
| Constraint | Effect | Approach |
|---|---|---|
| Queue delays are at most 12 hours | Long delayed jobs cannot be scheduled in one message | Scheduled notes and poll endings run on Durable Object alarms. The 24-hour wait in account migration is split into several waits |
| A Worker cannot list or delete Queue messages | Upstream's job admin UI cannot be reproduced | Failed and delayed jobs are recorded in a Durable Object and shown within that range. Waiting jobs cannot be shown or deleted |
Network and external services
| Constraint | Effect | Approach |
|---|---|---|
| The peer IP address is not visible and DNS cannot be queried | SSRF cannot be checked on the resolved address | Hosts are checked by name, on every redirect |
| No SMTP (TCP) sending | Upstream's mail settings cannot be used | Mail goes through Cloudflare Email Service (requires the Workers Paid plan) |
| The request body limit depends on the zone's plan (100 MB on Free / Pro) | The upload limit cannot exceed the plan | The default limit matches the plan. Upstream clients upload in a single request, so chunked uploads are not adopted |
| Native modules (sharp, ffmpeg) cannot run in a Worker | Images and videos cannot be converted | They run in Containers. Uploads succeed even when the Container is down; only thumbnails are missing |
| A machine-learning model would make the Container much larger and heavier | Automatic sensitive-media detection is not possible | Not supported (the settings are stored but have no effect) |
Database
| Constraint | Effect | Approach |
|---|---|---|
| Workers reach PostgreSQL through Hyperdrive | Connections are costly | One connection serves a whole request. The Workers run close to the database (Smart Placement) |
| Hyperdrive's SELECT cache is not invalidated by writes | Reads right after writes can be stale | The cache is disabled |
| Cloudflare D1 is SQLite | An existing Misskey database could not be carried over | Not used. Durable Object SQLite is used only for the Durable Objects' own state |
Deployment
| Constraint | Effect | Approach |
|---|---|---|
| Binding another Worker's Durable Object requires the owning Worker to be deployed first | Deploy order has dependencies | References point one way only; deploy in the order stream, timeline, media, api, gateway |
| Workers are also published on a workers.dev subdomain by default | Entrances that differ from the instance URL, or bypass the gateway, appear | Only the gateway's custom domain is public; the other Workers' public URLs are disabled |