Browse docs

Services

Function AppComing soon

Write a function in TypeScript, JavaScript or Python and get an HTTPS address for it, with your project's variables already set.

Coming soon. This feature is coming soon. It is not available to deploy yet; this page describes how it will work.

How it works

Click Create function on the Function App card of the project's Services tab. Give it a name, pick a runtime, write the handler and click Deploy (or deploy a file from your terminal, below). We build it and it is live at https://<name>-<project>.<apps domain> in about a minute.

  1. Every request to the address, with any method and path, calls your handler.
  2. The project's variables are set for it: DATABASE_URL, REDIS_URL, the S3_* storage keys, AUTH_*, EMAIL_*, JOBS_* and your custom variables, as on the Environment tab. They are read each time the function starts, so new services and new passwords are picked up.
  3. After 10 minutes without requests it stops. The next request starts it again in about a second: it is held while the function starts and then sent on, with its method and body (a 307 redirect to the same address).
  4. You pay for requests and the time they take, not for the hours it waits.

TypeScript and JavaScript

Node.js 24. Put the handler in index.ts (or index.js) as the default export. It gets a standard web Request and returns a Response; a string or an object is sent for you, as text or JSON. TypeScript runs as is: types are removed, so use plain syntax (no enum or namespace).

index.ts
TypeScript
import pg from "pg";

// Created once per start, and reused by every request.
const pool = new pg.Pool({ connectionString: process.env.DATABASE_URL, max: 5 });

export default async function handler(request: Request): Promise<Response> {
  const url = new URL(request.url);
  if (request.method === "POST") {
    const { title } = await request.json();
    const { rows } = await pool.query("insert into todos (title) values ($1) returning *", [title]);
    return Response.json(rows[0], { status: 201 });
  }
  const { rows } = await pool.query("select * from todos order by id desc limit $1", [url.searchParams.get("limit") ?? 20]);
  return Response.json(rows);
}
Dependencies (package.json)
JSON
{
  "dependencies": {
    "pg": "^8.13.0"
  }
}

Dependencies are installed with npm install on every deploy. The handler is an ES module unless package.json sets another type.

Python

Python 3.13. Define handler(request) in main.py, plain or async. request has method, path, query (a dict), headers (lowercase keys), body (bytes), text and json(). Return a dict or list (sent as JSON), a string, bytes, None (204), or a tuple of the body, the status and a dict of headers.

main.py
Python
import os
import psycopg

def handler(request):
    if request.method == "POST":
        title = request.json()["title"]
        with psycopg.connect(os.environ["DATABASE_URL"]) as db:
            row = db.execute("insert into todos (title) values (%s) returning id", [title]).fetchone()
        return {"id": row[0], "title": title}, 201
    return {"hello": request.query.get("name", "world")}
Dependencies (requirements.txt)
Text
psycopg[binary]==3.2.3

Call it

Shell
curl "https://api-my-project.example.app/todos?limit=5"
curl -X POST https://api-my-project.example.app/todos -H "content-type: application/json" -d '{"title":"Ship it"}'
  • The address is public. Check a token or a signature in the handler for anything private, for example a header your app sends with a secret from its own variables.
  • Answer CORS yourself when browsers call it from another site: return the access-control-allow-* headers, and answer OPTIONS.
  • An uncaught error answers 500 and is written to the Logs tab. A request that takes longer than the plan's timeout answers 504.
  • Clients that do not follow redirects (curl without -L) may see the 307 on the first request after the function slept.

Deploy from your terminal

You can also deploy a file without opening the dashboard. Create function shows these steps with your project id filled in, under Deploy from terminal.

1. Create hello.ts
TypeScript
export default {
  fetch: (request: Request) => new Response("Hello world"),
};
2. Set your API key (Show my key, or the Coding agent page)
Shell
export CLOUDHIKE_API_KEY="icu_..."
3. Deploy
Shell
curl -X PUT "https://cloudhike.dev/api/v1/projects/<project id>/functions/hello?file=hello.ts" \
  -H "Authorization: Bearer $CLOUDHIKE_API_KEY" \
  --data-binary @hello.ts
  • The last part of the address is the function's name. Run the command again to deploy a change; use another name to add another function to the project.
  • The file's extension picks the runtime: .ts, .js or .mjs for Node.js, .py for Python. A function's runtime cannot change once it exists.
  • Add &environment=development to deploy to another environment, and &size=small to choose a size.
  • GET the same address for the function's status and url. GET .../functions lists the project's functions.
  • A JSON body works too: {"runtime": "node", "code": "...", "dependencies": "..."} with content-type: application/json.

Change, test and deploy

Edit the code on the function's Code & test tab and click Save and deploy; the running version keeps answering until the new one replaces it. The Test panel below it sends a request (any method, path, headers and body) to the deployed function and shows the status, time and response. Test requests are billed like any other. The row of names under the function's title moves between the project's functions, and New function adds one. Settings changes the size and adds variables of its own, which win over the project's. Logs shows the last 200 lines it wrote. AI editors connected through the MCP server can create and update functions with the deploy_function tool.

Limits and pricing

FreePro
Functions per project2No limit
SizesMicro (256 MB)Micro to Large (2 GB)
Longest request30 seconds5 minutes
Each month, per function100,000 requests and 25,000 GB-seconds, then it stops until the next month100,000 requests and 25,000 GB-seconds included, then $0.40 per million requests and $0.012 per 1,000 GB-seconds
Code512 KB512 KB
  • GB-seconds are the time requests take, from arriving to the last byte of the answer, at the function's memory size: one second at 256 MB is 0.25 GB-seconds.
  • Usage is counted every few minutes, so a Free function can go a little past its month before it stops. Upgrading to Pro starts it again.
  • Requests and compute are charged from your credits every hour, like email and background jobs. The function's page shows this month's use.
  • The function's disk is read-only; /tmp can be written, is kept in memory and is emptied when it stops. Keep data in Postgres, Redis or Storage.

Use with AI

Let your coding agent write and deploy a function for your backend.

  1. 1

    Open a terminal in your app's folder and start Claude Code.

    Terminal
    Shell
    claude
  2. 2

    Paste the prompt below and press Enter. Approve the file edits and commands it asks about.

  3. 3

    Optional: save a short note about CloudHike.dev in CLAUDE.md so every session knows about it.

PROMPT
Read https://cloudhike.dev/docs/md/functions. Write a CloudHike.dev function for this app's API: an index.ts default export that takes a Request and returns a Response, using DATABASE_URL from process.env, with its package.json dependencies. Deploy it with the deploy_function MCP tool, wait for it with wait_for_services, and call it from the app at the url it returns.

Replace the placeholders in <angle brackets> before sending. Always review what the agent changes.