Configure AWS Kendra FAQs

The aws:kendra/faq:Faq resource, part of the Pulumi AWS provider, loads FAQ question-answer pairs from S3 into a Kendra index for natural language search. This guide focuses on three capabilities: S3-based FAQ ingestion, file format specification, and language code configuration.

FAQs depend on an existing Kendra index, an IAM role with S3 read permissions, and S3 objects containing properly formatted FAQ data. The examples are intentionally small. Combine them with your own index, IAM roles, and S3 content.

Load FAQ data from S3 into a Kendra index

Teams building search applications maintain FAQ documents in S3 and load them into Kendra for natural language queries.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const example = new aws.kendra.Faq("example", {
    indexId: exampleAwsKendraIndex.id,
    name: "Example",
    roleArn: exampleAwsIamRole.arn,
    s3Path: {
        bucket: exampleAwsS3Bucket.id,
        key: exampleAwsS3Object.key,
    },
    tags: {
        Name: "Example Kendra Faq",
    },
});
import pulumi
import pulumi_aws as aws

example = aws.kendra.Faq("example",
    index_id=example_aws_kendra_index["id"],
    name="Example",
    role_arn=example_aws_iam_role["arn"],
    s3_path={
        "bucket": example_aws_s3_bucket["id"],
        "key": example_aws_s3_object["key"],
    },
    tags={
        "Name": "Example Kendra Faq",
    })
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/kendra"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := kendra.NewFaq(ctx, "example", &kendra.FaqArgs{
			IndexId: pulumi.Any(exampleAwsKendraIndex.Id),
			Name:    pulumi.String("Example"),
			RoleArn: pulumi.Any(exampleAwsIamRole.Arn),
			S3Path: &kendra.FaqS3PathArgs{
				Bucket: pulumi.Any(exampleAwsS3Bucket.Id),
				Key:    pulumi.Any(exampleAwsS3Object.Key),
			},
			Tags: pulumi.StringMap{
				"Name": pulumi.String("Example Kendra Faq"),
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var example = new Aws.Kendra.Faq("example", new()
    {
        IndexId = exampleAwsKendraIndex.Id,
        Name = "Example",
        RoleArn = exampleAwsIamRole.Arn,
        S3Path = new Aws.Kendra.Inputs.FaqS3PathArgs
        {
            Bucket = exampleAwsS3Bucket.Id,
            Key = exampleAwsS3Object.Key,
        },
        Tags = 
        {
            { "Name", "Example Kendra Faq" },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.kendra.Faq;
import com.pulumi.aws.kendra.FaqArgs;
import com.pulumi.aws.kendra.inputs.FaqS3PathArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var example = new Faq("example", FaqArgs.builder()
            .indexId(exampleAwsKendraIndex.id())
            .name("Example")
            .roleArn(exampleAwsIamRole.arn())
            .s3Path(FaqS3PathArgs.builder()
                .bucket(exampleAwsS3Bucket.id())
                .key(exampleAwsS3Object.key())
                .build())
            .tags(Map.of("Name", "Example Kendra Faq"))
            .build());

    }
}
resources:
  example:
    type: aws:kendra:Faq
    properties:
      indexId: ${exampleAwsKendraIndex.id}
      name: Example
      roleArn: ${exampleAwsIamRole.arn}
      s3Path:
        bucket: ${exampleAwsS3Bucket.id}
        key: ${exampleAwsS3Object.key}
      tags:
        Name: Example Kendra Faq

When you create the FAQ resource, Kendra reads the file from S3 and indexes the question-answer pairs. The indexId connects to your existing Kendra index. The s3Path specifies the bucket and key where your FAQ file lives. The roleArn grants Kendra permission to read from S3; this role must have S3 read access and trust Kendra as a principal.

Specify CSV format for FAQ data

FAQ files can be stored in different formats. Setting the file format ensures Kendra parses the content correctly.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const example = new aws.kendra.Faq("example", {
    indexId: exampleAwsKendraIndex.id,
    name: "Example",
    fileFormat: "CSV",
    roleArn: exampleAwsIamRole.arn,
    s3Path: {
        bucket: exampleAwsS3Bucket.id,
        key: exampleAwsS3Object.key,
    },
});
import pulumi
import pulumi_aws as aws

example = aws.kendra.Faq("example",
    index_id=example_aws_kendra_index["id"],
    name="Example",
    file_format="CSV",
    role_arn=example_aws_iam_role["arn"],
    s3_path={
        "bucket": example_aws_s3_bucket["id"],
        "key": example_aws_s3_object["key"],
    })
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/kendra"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := kendra.NewFaq(ctx, "example", &kendra.FaqArgs{
			IndexId:    pulumi.Any(exampleAwsKendraIndex.Id),
			Name:       pulumi.String("Example"),
			FileFormat: pulumi.String("CSV"),
			RoleArn:    pulumi.Any(exampleAwsIamRole.Arn),
			S3Path: &kendra.FaqS3PathArgs{
				Bucket: pulumi.Any(exampleAwsS3Bucket.Id),
				Key:    pulumi.Any(exampleAwsS3Object.Key),
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var example = new Aws.Kendra.Faq("example", new()
    {
        IndexId = exampleAwsKendraIndex.Id,
        Name = "Example",
        FileFormat = "CSV",
        RoleArn = exampleAwsIamRole.Arn,
        S3Path = new Aws.Kendra.Inputs.FaqS3PathArgs
        {
            Bucket = exampleAwsS3Bucket.Id,
            Key = exampleAwsS3Object.Key,
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.kendra.Faq;
import com.pulumi.aws.kendra.FaqArgs;
import com.pulumi.aws.kendra.inputs.FaqS3PathArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var example = new Faq("example", FaqArgs.builder()
            .indexId(exampleAwsKendraIndex.id())
            .name("Example")
            .fileFormat("CSV")
            .roleArn(exampleAwsIamRole.arn())
            .s3Path(FaqS3PathArgs.builder()
                .bucket(exampleAwsS3Bucket.id())
                .key(exampleAwsS3Object.key())
                .build())
            .build());

    }
}
resources:
  example:
    type: aws:kendra:Faq
    properties:
      indexId: ${exampleAwsKendraIndex.id}
      name: Example
      fileFormat: CSV
      roleArn: ${exampleAwsIamRole.arn}
      s3Path:
        bucket: ${exampleAwsS3Bucket.id}
        key: ${exampleAwsS3Object.key}

The fileFormat property tells Kendra how to interpret the file structure. CSV format expects columns for questions and answers. Without this property, Kendra infers the format from the file extension.

Set language for FAQ content processing

Kendra uses language-specific processing for tokenization and stemming. Setting the language code improves search relevance.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const example = new aws.kendra.Faq("example", {
    indexId: exampleAwsKendraIndex.id,
    name: "Example",
    languageCode: "en",
    roleArn: exampleAwsIamRole.arn,
    s3Path: {
        bucket: exampleAwsS3Bucket.id,
        key: exampleAwsS3Object.key,
    },
});
import pulumi
import pulumi_aws as aws

example = aws.kendra.Faq("example",
    index_id=example_aws_kendra_index["id"],
    name="Example",
    language_code="en",
    role_arn=example_aws_iam_role["arn"],
    s3_path={
        "bucket": example_aws_s3_bucket["id"],
        "key": example_aws_s3_object["key"],
    })
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/kendra"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := kendra.NewFaq(ctx, "example", &kendra.FaqArgs{
			IndexId:      pulumi.Any(exampleAwsKendraIndex.Id),
			Name:         pulumi.String("Example"),
			LanguageCode: pulumi.String("en"),
			RoleArn:      pulumi.Any(exampleAwsIamRole.Arn),
			S3Path: &kendra.FaqS3PathArgs{
				Bucket: pulumi.Any(exampleAwsS3Bucket.Id),
				Key:    pulumi.Any(exampleAwsS3Object.Key),
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var example = new Aws.Kendra.Faq("example", new()
    {
        IndexId = exampleAwsKendraIndex.Id,
        Name = "Example",
        LanguageCode = "en",
        RoleArn = exampleAwsIamRole.Arn,
        S3Path = new Aws.Kendra.Inputs.FaqS3PathArgs
        {
            Bucket = exampleAwsS3Bucket.Id,
            Key = exampleAwsS3Object.Key,
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.kendra.Faq;
import com.pulumi.aws.kendra.FaqArgs;
import com.pulumi.aws.kendra.inputs.FaqS3PathArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var example = new Faq("example", FaqArgs.builder()
            .indexId(exampleAwsKendraIndex.id())
            .name("Example")
            .languageCode("en")
            .roleArn(exampleAwsIamRole.arn())
            .s3Path(FaqS3PathArgs.builder()
                .bucket(exampleAwsS3Bucket.id())
                .key(exampleAwsS3Object.key())
                .build())
            .build());

    }
}
resources:
  example:
    type: aws:kendra:Faq
    properties:
      indexId: ${exampleAwsKendraIndex.id}
      name: Example
      languageCode: en
      roleArn: ${exampleAwsIamRole.arn}
      s3Path:
        bucket: ${exampleAwsS3Bucket.id}
        key: ${exampleAwsS3Object.key}

The languageCode property enables language-specific text processing. For example, “en” applies English stemming rules (e.g., “running” matches “run”). This improves search quality for non-English content by applying appropriate linguistic rules.

Beyond these examples

These snippets focus on specific FAQ-level features: S3-based FAQ ingestion, file format specification, and language-specific processing. They’re intentionally minimal rather than full search implementations.

The examples reference pre-existing infrastructure such as Kendra indexes, IAM roles with S3 read permissions, and S3 buckets with FAQ content. They focus on configuring the FAQ resource rather than provisioning the surrounding infrastructure.

To keep things focused, common FAQ patterns are omitted, including:

  • FAQ file format requirements and structure
  • Description metadata (description property)
  • Status monitoring and error handling
  • Update and versioning workflows

These omissions are intentional: the goal is to illustrate how FAQ ingestion is wired, not provide drop-in search modules. See the Kendra FAQ resource reference for all available configuration options.

Let's configure AWS Kendra FAQs

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Configuration & Setup
What IAM permissions does the role need for a Kendra FAQ?
The roleArn must have permissions to access the S3 bucket containing the FAQ data. See the AWS documentation on IAM Roles for Amazon Kendra for specific permission requirements.
What file formats are supported for FAQ data?
You can specify the format using the fileFormat property. The example shows CSV format.
How do I specify the language for my FAQ?
Set the languageCode property (required). For example, use "en" for English.
Resource Management
What properties can't I change after creating a FAQ?
The following properties are immutable and force replacement if changed: indexId, name, roleArn, s3Path, languageCode, description, and fileFormat. Only tags can be modified.
How do I import an existing Kendra FAQ?
Use the format faq-id/index-id separated by a slash. For example: pulumi import aws:kendra/faq:Faq example faq-123456780/idx-8012925589
Monitoring & Status
How do I monitor my FAQ's creation status?
Check the status output property. The FAQ is ready when status is ACTIVE. If status is FAILED, the errorMessage field explains what went wrong.

Using a different cloud?

Explore analytics guides for other cloud providers: