Skip to content

Conversation

@alexellis
Copy link
Member

@alexellis alexellis commented Nov 11, 2025

Description

Add "inproc" mode for Golang functions

Motivation and Context

Reduce total RAM usage by running a single process for the watchdog and the handler of a function (only possible with Go)

Roundtrip latency may also be improved for function invocations.

How Has This Been Tested?

Initial testing in Kubernetes with a modified template appears to work as expected.

To achieve a similar effect to prefixing each logged line with a Call ID bespoke code will be required:

package function

import (
	"fmt"
	"io"
	"log/slog"
	"os"

	"net/http"
	"time"
)

func Handle(w http.ResponseWriter, r *http.Request) {
	var input []byte

	log := slog.New(slog.NewTextHandler(os.Stdout, opts))
	log = log.With("X-Call-Id", r.Header.Get("X-Call-Id"))

	log.Info("received request")

	if r.Body != nil {
		defer r.Body.Close()

		body, _ := io.ReadAll(r.Body)

		input = body
	}

	log.Info("Sleeping for 1 milliseconds")

	time.Sleep(time.Millisecond * 1)

	log.Info("Sleep done")

	w.WriteHeader(http.StatusOK)
	w.Write([]byte(fmt.Sprintf("Body: %s", string(input))))
}

Initial RAM usage showed as 2Mi and rose over time to 4Mi

$ kubectl top pod -n openfaas-fn| grep "ofw"
ofw-d67d7c474-rpx8c             1m           4Mi  

The printer function from the store is showing about 11Mi of usage and does very little in and of itself other than logging the incoming HTTP request:

$ kubectl top pod -n openfaas-fn| grep "printer"
printer-5c9b5fbf98-gbwn7        1m           11Mi  

Custom template that imports the new watchdog "SDK":

https://github.com/openfaas/golang-http-template/blob/inproc/template/golang-middleware-inproc/main.go

Types of changes

On the plus side - RAM looks to be much smaller as low as 2mb total usage vs the two processes.

On the downside, it's not possible or practical to do stderr/stdout prefixing due to no process boundary between the watchdog and the handler process.

A new template and Dockerfile will be required to support the changes. Builds may be marginally slower since they have to import the watchdog as an "SDK".

Every push will be a single layer binary so this will also take longer vs a tiny Go binary plus the watchdog.

Checklist:

The change will have to be explained and documented as an alternative. Unless it becomes the default, I can't imagine uptake being large other than for internal use and with select customers who learn about it from us.

The watchdog can be imported by a Go template in order to
avoid any hop over HTTP.

On the plus side - RAM looks to be much smaller as low as
2mb total usage vs the two processes.

On the downside, it's not possible or practical to do
stderr/stdout prefixing due to no process boundary between
the watchdog and the handler process.

A new template and Dockerfile will be required to support
the changes. Builds may be marginally slower since they have
to import the watchdog as an "SDK".

Every push will be a single layer binary so this will also
take longer vs a tiny Go binary plus the watchdog.

Initial testing in Kubernetes with a modified template
appears to work as expected.

Signed-off-by: Alex Ellis (OpenFaaS Ltd) <alexellis2@gmail.com>
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces an "inproc" (in-process) mode for Golang functions, allowing the watchdog and function handler to run in a single process instead of spawning separate processes. This architectural change aims to reduce total RAM usage and potentially improve roundtrip latency for function invocations, with initial testing showing approximately 2-4 MB RAM usage compared to 11 MB for traditional separate-process mode.

Key changes:

  • Adds new ModeInproc operational mode with corresponding configuration and executor
  • Refactors main watchdog logic from main.go into pkg/watchdog.go to enable reusability
  • Changes package structure from main to pkg for core watchdog components

Reviewed Changes

Copilot reviewed 10 out of 11 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
vendor/modules.txt Adds google/uuid dependency for the new inproc mode
go.mod Removes gorilla/mux from indirect dependencies
config/config_modes.go Defines ModeInproc constant and adds "inproc" mode support
config/config.go Adds Handler field and allows empty fprocess for inproc/static modes
config/config_test.go Tests that inproc mode allows missing fprocess configuration
executor/inproc_runner.go Implements InprocRunner for executing handlers in-process
pkg/watchdog.go Refactored watchdog logic extracted from main.go into reusable package
main.go Simplified to use new pkg.Watchdog with minimal bootstrapping code
requesthandler_test.go Updates package from main to pkg and adjusts health handler calls
readiness_test.go Updates package from main to pkg
readiness.go Updates package from main to pkg

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@alexellis alexellis merged commit 67a6309 into master Nov 14, 2025
8 checks passed
@alexellis
Copy link
Member Author

Reviewed by opencode / Big Pickle.. no significant issues detected.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants