Polyglot APIs with File-Based Routing in FastFN¶
Verified status as of March 28, 2026. Runtime note: FastFN auto-installs function-local dependencies from
requirements.txt/package.json; host runtimes are required infastfn dev --native, whilefastfn devdepends on a running Docker daemon. FastFN now supports a practical polyglot workflow: one gateway, one routing model, multiple runtimes in the same app tree.
This article summarizes what that means in real projects and why it reduces operational friction.
1) One URL model across languages¶
With file-based routing, paths come from filenames, not per-runtime adapters.
Example from examples/functions/next-style:
users/index.js->GET /users(Node)users/[id].js->GET /users/:id(Node)blog/[...slug].py->GET /blog/:slug*(Python)php/get.profile.[id].php->GET /php/profile/:id(PHP)rust/get.health.rs->GET /rust/health(Rust)admin/post.users.[id].py->POST /admin/users/:id(Python)
The important part is parity: the routing rules stay the same even when runtime changes.
2) Runtime choice becomes a file-level decision¶
In a polyglot service, teams often migrate endpoint-by-endpoint:
- Keep stable paths.
- Rewrite one handler in another language.
- Keep OpenAPI and gateway policy behavior consistent.
Because runtime is inferred from extension (.js, .py, .php, .rs), this migration path is incremental and low-risk.
3) Explicit overrides still work¶
You are not locked into pure file routing:
fn.config.json(highest priority)fn.routes.json- file-based routes
This allows mixed strategies:
- Most routes zero-config.
- Selected routes explicitly mapped in
fn.routes.json. - Special policy/runtime tuning in
fn.config.json.
In tests/fixtures/polyglot-demo, this pattern is used to mix Node/Python/PHP/Rust handlers with explicit route mapping.
4) Unified OpenAPI for mixed runtimes¶
A common polyglot problem is fragmented docs per language stack.
FastFN generates one gateway-level OpenAPI from discovered routes, so consumers see one API surface even when handlers are split across runtimes.
Operationally, this helps:
- SDK generation from one spec.
- Cleaner contract reviews.
- Fewer mismatches between teams.
5) Better local dev for monorepos¶
fastfn dev <root> mounts the full root in development, so adding new files/folders is reflected without manual remount workflows.
For polyglot repos, this avoids the classic issue where one runtime hot-reloads but another requires rebuild scripts.
6) Warm/cold visibility across runtimes¶
Responses expose runtime state headers:
X-FastFN-Function-State: cold|warmX-FastFN-Warmed: trueX-FastFN-Warming: truewithRetry-After: 1
This matters more in polyglot setups, where startup behavior differs by runtime (for example Rust first-build vs interpreted runtimes).
7) Practical adoption path¶
Recommended sequence:
- Start with file-based routes in one folder.
- Add cross-runtime endpoints in the same tree.
- Introduce
fn.routes.jsononly where explicit control is needed. - Keep
fn.config.jsonfor policy/concurrency/timeouts, not for every route. - Validate with integration suite before rollout.
Result: one platform contract, language flexibility, and lower operational overhead than maintaining separate gateways per runtime.
Key takeaway¶
The biggest win is not just "many languages." It is one URL tree, one deployment surface, and one OpenAPI document even when different teams choose different runtimes.
What to keep in mind¶
- File extension decides the runtime, but the URL comes from the same folder rules everywhere.
- Keep shared policy in
fn.config.json; usefn.routes.jsononly when you really need an override. - Validate warm and cold behavior in each runtime before moving latency-sensitive endpoints.
When this approach is worth it¶
- Use it when teams share one API surface but not one language.
- Keep a single runtime if the whole service has the same tooling and performance needs.
- Use explicit route overrides for legacy paths or special cases, not as the default way to build new endpoints.