Technology Blog Posts by Members
cancel
Showing results for 
Search instead for 
Did you mean: 
neilaspin
Explorer
449

Ever tried to make AWS Lambda talk to a Kyma Function on SAP BTP and ended up buried in docs and 400 errors? Same. In this post, I’ll walk you through the simplest setup that actually works — a Lambda sending JSON to Kyma over HTTPS, step by step.

(In the code snippets, substitute KYMA_CLUSTER_DOMAIN with your Kyma Cluster Domain.)

To recreate this setup, you only need a few free-tier tools and basic access:

Accounts & Platforms

  • AWS Free Tier account – with permissions to create and run a Lambda function.
  • SAP BTP Free Tier account – with access to the Kyma runtime (trial or free tier).
  • GitHub (optional) – if you want to version your function or YAML files.

Local Tools

  • Shell or Terminal – any terminal works (Mac Terminal, Windows PowerShell, WSL, etc.).
  • kubectl – the Kubernetes CLI, configured to connect to your Kyma cluster.
  • Visual Studio Code (VSC) – for editing the function code and YAML files (not strictly necessary, but a nice to have!)
  • curl – to test your public Kyma endpoint from the command line.

First, we’ll create a function called message-function. You’ll find Functions under Namespaces → your_namespace → Functions.

Click Create, name it message-function, set the language to JavaScript and the runtime to Node.js 22. Leave the rest as default.

Screenshot 2025-10-17 at 07.09.54.png

In the Source tab, add the following code:

module.exports = {
  main: async function (event, context) {
    let input;
    try {
      if (!event.data) {
        input = {};
      } else if (typeof event.data === "string") {
        input = JSON.parse(event.data);
      } else {
        input = event.data;
      }
    } catch (err) {
      console.error("Parse error:", err.message);
      return {
        statusCode: 400,
        body: {
          error: "Invalid JSON payload",
          details: err.message
        }
      };
    }

    console.log("Received payload:", input);

    return {
      statusCode: 200,
      body: {
        message: "Hello from Kyma — message-function working!",
        received: input
      }
    };
  }
};

Click Create.

Screenshot 2025-10-17 at 07.04.43.png

Click Save and wait for the function to reach a Running state (you’ll briefly see Unknown):

Monosnap Image 2025-10-24 09-57-39.png

It should switch to Ready after a few seconds:

Screenshot 2025-10-17 at 07.14.10.png

Create a file named message-function-apirule.yaml with the following content and apply it:

apiVersion: gateway.kyma-project.io/v1beta1
kind: APIRule
metadata:
  name: message-function
spec:
  gateway: kyma-gateway.kyma-system.svc.cluster.local
  host: message-function
  service:
    name: message-function
    port: 80
  rules:
    - path: /.*
      methods: ["GET", "POST"]
      accessStrategies:
        - handler: allow
$ kubectl apply -f message-function-apirule.yaml

You should see:

apirule.gateway.kyma-project.io/message-function created

Check your namespace:

$ kubectl get apirule -n dev

You’ll get something like:

message-function     Ready ["message-function.<KYMA_CLUSTER_DOMAIN>"]

Test it again:

$ curl -X POST https://message-function.<KYMA_CLUSTER_DOMAIN> \
  -H "Content-Type: application/json" \
  -d '{"test":"direct"}'

You should see a response like:

Hello world from the Kyma Function message-function running on Node.js 22!

Now let’s work through the Lambda part.

In AWS Console → Lambda → Functions → Create Function:

Screenshot 2025-10-17 at 08.01.51.png

Add this code to your index.mjs file:

// index.js (CommonJS)
const https = require("https");

exports.handler = async (event) => {
  const data = JSON.stringify({
    from: "AWS Lambda",
    time: new Date().toISOString(),
    echo: event || {}
  });

  const options = {
    hostname: "message-function.<KYMA_CLUSTER_DOMAIN>",
    port: 443,
    path: "/",
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "Content-Length": Buffer.byteLength(data)
    }
  };

  return new Promise((resolve, reject) => {
    const req = https.request(options, (res) => {
      let body = "";
      res.on("data", (chunk) => (body += chunk));
      res.on("end", () => {
        console.log("Kyma replied:", body);
        resolve({ statusCode: res.statusCode, body });
      });
    });

    req.on("error", (err) => {
      console.error("HTTPS error:", err);
      reject(err);
    });

    req.write(data);
    req.end();
  });
};

Create a test event with the JSON: { "hello": "world" }

Screenshot 2025-10-17 at 08.24.00.png

Click Test (top right corner). You should see:

Screenshot 2025-10-17 at 08.26.25.png

Then click the Logs link to open CloudWatch:

Screenshot 2025-10-17 at 08.27.23.png

Open the latest log stream and you’ll see something like:

Screenshot 2025-10-17 at 08.30.10.png

And we’re golden!

2025-10-17T07:24:39.081Z 141aa77f-cbdd-4c28-b74a-d56c18519d3e INFO Kyma replied: Hello world from the Kyma Function message-function running on Node.js 22!

Conclusion:

With just a Kyma Function, an APIRule, and a few lines of Node.js in AWS Lambda, we’ve built a working integration between AWS and SAP BTP. The Lambda sends a simple JSON payload over HTTPS, Kyma processes it, and responds in real time. The result is lightweight, reliable, and scalable — perfect for triggering SAP workloads from AWS events without extra middleware or services.