Skip to content

Develop a new Application Service

Using Application Service Template

To help users build a custom Application Service, IOTech provides a template in the proprietary Application Service SDK, which is based on the EdgeX community's app-service-template.

If you are new to Application Functions SDK, it is recommended to read this article Application Functions SDK - EdgeX Foundry Documentation first.

This template contains a buildable/runnable sample for a new custom application service based on the 2.1.x release of the Edge Xpert Application Functions SDK.


To create your own Application Services using Edge Xpert Application Service SDK, you will need a certain level of knowledge on writing Go programs. If built-in pipeline functions can satisfy your requirement, it is advisable that you use Edge Xpert Application Service Configurable rather than creating a new custom application service.

Follow the instructions below to create your new custom application service:

  1. Create a new folder on your local file system and use it as the working directory for the following steps.

  2. Copy all contents of edgexpert-app-service-template except configurable to the working directory.

  3. Create a folder named app-functions-sdk-go-private in the working directory, and copy all the SDK contents except edgexpert-app-service-template into it.

  4. Update the go.mod file in the working directory. (Go modules is a dependency management tool of Go.)

    • Change the Go Module name new-app-service in go.mod to an appropriate name for your service.
    • Typically this is the URL to the repository for your service. For example, if you create a repository named MyAppService on GitHub for your application, then you can use as the module name.
  5. Do a global search for new-app-service in the following files to replace it with the name of your service.

    • makefile
    • Dockerfile
    • main.go


    The name will be used as the service key for the Configuration and Registry Service (i.e. Consul), and you should avoid using any special characters for its value.


    If you change the Go Module name to a URL in step 4, you should also update the import statement inside main.go to match the name you provided in the go.mod file. For example, if the Go Module name is changed from new-app-service to, the local import statement should be updated accordingly, as shown in the following extract:

    import (
        "" // Note this line

  6. Run unit tests to verify changes didn't break the code.

    • Open a terminal.
    • Enter the following command:
      cd /path/to/workDir # See step 1
      make test
  7. Verify you are able to build the Go source code to an executable binary. In the terminal opened in step 6, enter the following command:

    make build

  8. Verify you are able to build the docker image. In the terminal opened in step 6, enter the following command:

    make docker

  9. Resolve all TODOs as listed in following files for your custom code:

    • makefile - defines set of tasks to be executed, such as running unit tests, building executable binary and docker image.

    • Dockerfile - defines all instructions to assemble a docker image. For more details about Dockerfile, please refer to Dockerfile reference.

    • main.go - defines the main package with a func main() for building an executable. The main.go will initialize an SDK instance and set up the functions pipeline.

    • functions/sample.go - provides a sample implementation for following custom pipeline functions:

      • LogEventDetails - prints out the incoming EdgeX Event and then pass the Event to next pipeline function.
      • ConvertEventToXML - transforms incoming EdgeX Event to XMl format and then pass the transformed data to next pipeline function.
      • OutputXML - sets the response data that will be returned to the trigger when pipeline execution is complete. The response data will be in XML format.
    • functions/sample_test.go - contains unit tests for the above pipeline functions.

    • res/configuration.toml - defines the default configuration for Application Service.

  10. Repeat steps 6, 7, and 8 to verify and build your custom application service.

  11. To use your custom application service in Edge Xpert, copy the following docker-compose files to your working directory.

    • /etc/edgexpert/app-service.yml
    • /etc/edgexpert/app-service-security.yml
    cp /etc/edgexpert/app-service.yml /path/to/workDir/.
    cp /etc/edgexpert/app-service-security.yml /path/to/workDir/.

    Update docker-compose files with your app service docker image name and tag:

        image: name:tag


    The name and tag should match the values you specified for the -t option of the docker build command inside the makefile. You can also use command below to find the name and tag of your app service docker image:

    docker images
    The app service image as built in step 10 should be listed at the top of the image list:
    REPOSITORY                 TAG     IMAGE ID       CREATED         SIZE
    example/my-app-service     dev     b209a554e44f   1 hours ago     33MB
    In this case, the image name is example/my-app-service and tag is dev.

  12. Launch your custom application service with Edge Xpert. Open a terminal and enter command below:

    cd /path/to/workDir
    edgexpert up app-service -p <path to the configuration toml file>


    edgexpert CLI will look for docker-compose files residing in the current folder first. For further information on edgexpert CLI, refer to Edge Xpert CLI Tool.

Create new configurable pipeline functions

To create new configurable pipeline functions, you will need to do the following: - Add the pipeline function implementation to the package pkg/transforms of the SDK. - Add the configurable function implementation to the package appsdk of the SDK.

The configurable function is a helper function invoked by the LoadConfigurablePipeline function of the SDK to parse the [Writable.Pipeline.Functions.{FunctionName}.Parameters] configuration into the actual parameters required by the pipeline function.


The Parameters section for each function is defined in key/value pairs. You will need to convert each pair of key/value to corresponding value types as need by the configuration function.

The configurable function should have the following function signature if your configurable function requires parameters:

func (dynamic AppFunctionsSDKConfigurable) YourFunctionName(parameters map[string]string) appcontext.AppFunction
If your configurable function does not require any parameter, use function signature below:
func (dynamic AppFunctionsSDKConfigurable) YourFunctionName() appcontext.AppFunction
The output result of a configuration function should be a function pointer to the target built-in/custom function.

The configurable/sample_configurable.go provides a sample implementation that shows how to make configurable functions for the sample functions. Follow instructions below to add the sample files into SDK to build a custom configurable application service:

  1. Complete all steps as listed in the previous section.

  2. Copy functions/sample.go and functions/sample_test.go to app-functions-sdk-go-private/pkg/transforms

  3. Rename the package name inside the sample.go and sample_test.go from functions to transforms.

  4. Copy configurable/sample_configurable.go to app-functions-sdk-go-private/internal/app/sample_configurable.go.

  5. Modify main.go to use the LoadConfigurablePipeline method of SDK to read Pipeline function settings from configuration.toml:

    appFunctions, err := edgexSdk.LoadConfigurablePipeline()
    if err != nil {
        edgexSdk.LoggingClient.Error("failed to create function pipeline from configuration: " + err.Error())

  6. Follow step 6, 7, and 8 as described in the previous section to run test and build image.

  7. To use these new configurable pipeline functions (LogEventDetails, ConvertEventToXML, and OutputXML), add following configuration into the [Writable] section of your service configuration toml file to define the pipeline:

    UseTargetTypeOfByteArray = false
    ExecutionOrder = "LogEventDetails, ConvertEventToXML, OutputXML"
      LogBinaryValue = "false"

Back to top