@cfxlabsinc/b2b-services
    Preparing search index...
    interface LambdaAppArgs {
        alarmTopicArn: Input<string>;
        aliasDependsOn?: Resource[];
        architecture: Input<"x86_64" | "arm64">;
        asyncInvoke?: {
            maximumEventAgeInSeconds: Input<number>;
            maximumRetryAttempts: Input<number>;
        };
        code?: LambdaS3Code
        | Archive;
        description?: Input<string>;
        environment?: Input<FunctionEnvironment>;
        handler?: Input<string>;
        layers?: Input<Input<string>[]>;
        legacyResourceNames?: { function?: string; logGroup?: string };
        memorySize?: Input<number>;
        privateSubnetIds: Input<string[]>;
        provisionedConcurrency?: {
            alarmOnSpillover?: boolean;
            grants?: (role: Role) => Resource[];
            provisionedConcurrentExecutions: Input<number>;
        };
        publish?: boolean;
        publishTopicArns?: Input<string>[];
        reservedConcurrentExecutions?: Input<number>;
        runtime?: Input<string>;
        slowResponseAlarmThresholdMs?: number;
        timeout?: Input<number>;
        usesIdempotencyTable?: boolean;
        vpcId: Input<string>;
        warningAlarms?: { description: string; key: string; pattern: string }[];
    }
    Index
    alarmTopicArn: Input<string>

    SNS topic for the init-failure alarm. Required, not optional: a lambda that silently ships without this alarm is the failure mode the alarm exists to prevent.

    aliasDependsOn?: Resource[]

    What the live alias waits for before it moves: a deploy's config gate.

    architecture: Input<"x86_64" | "arm64">

    Instruction set architecture for the function. Either "x86_64" or "arm64".

    asyncInvoke?: {
        maximumEventAgeInSeconds: Input<number>;
        maximumRetryAttempts: Input<number>;
    }

    Asynchronous invocations of the live alias, or of the function without one. Lambda retries a throttled event for six hours by default, so a caller that invokes again on its own, such as Temporal Cloud, keeps the age short.

    code?: LambdaS3Code | Archive

    The deployment package. Widened from FileArchive to Archive so a caller can pass an AssetArchive of inline source instead of a built bundle directory — the Outpost bridge in @cfxlabsinc/events is ~40 lines with no dependencies, so a bundle would buy it nothing. A FileArchive must name a built, non-empty directory, because its digest keys the Commit tag.

    Or an object already in S3, which is how the Bun lambdas ship: see declareLambdaArtifact.

    description?: Input<string>

    The published version's description, which Lambda records per version: a serverless worker's build id, so a version can be matched to its build.

    environment?: Input<FunctionEnvironment>
    handler?: Input<string>
    layers?: Input<Input<string>[]>
    legacyResourceNames?: { function?: string; logGroup?: string }

    Prior top-level Pulumi resource names, for an app moving onto LambdaApp from hand-rolled resources.

    A resource's Pulumi identity is its URN (type + name + parent), not its physical AWS name. Adopting this component changes both the name and the parent, so without an alias Pulumi plans a create — and AWS rejects it because the physical name is still held by the resource Pulumi is about to delete (ResourceAlreadyExistsException for the log group, ResourceConflictException for the function). Aliases re-bind the existing state entries to the new URNs so they update in place instead.

    memorySize?: Input<number>

    Amount of memory in MB your Lambda Function can use at runtime. Valid value between 128 MB to 10,240 MB (10 GB), in 1 MB increments. Defaults to 128.

    privateSubnetIds: Input<string[]>

    Private subnets the function's ENIs attach to.

    provisionedConcurrency?: {
        alarmOnSpillover?: boolean;
        grants?: (role: Role) => Resource[];
        provisionedConcurrentExecutions: Input<number>;
    }

    Sandboxes kept warm on the live alias.

    Type Declaration

    • OptionalalarmOnSpillover?: boolean

      Alarm when calls find every provisioned sandbox busy and cold-start on demand. Set it where traffic is steady and a spill means a caller waits; a bursty function spills by design.

    • Optionalgrants?: (role: Role) => Resource[]

      Built on the execution role before any sandbox is warmed, for the grants the handler's init reads with (an env parameter, say): a warm-up that runs first fails AccessDenied and leaves the config FAILED.

    • provisionedConcurrentExecutions: Input<number>
    publish?: boolean

    Publish a numbered version on every code or configuration change and point the live alias at it, for a caller that invokes the alias rather than $LATEST. Implied by provisionedConcurrency.

    publishTopicArns?: Input<string>[]

    SNS topics this function may publish to. Pass CUSTOMER_EVENTS_TOPIC_ARN to make it a public-bus publisher.

    The grant lands on this app's own execution role, declared here in the app's own stack — the same shape as its S3 and DynamoDB access, and the reason a new publisher cannot be forgotten in a list somewhere else and discover it at runtime as AccessDenied.

    Omitted or empty grants no publish access.

    reservedConcurrentExecutions?: Input<number>

    Concurrency set aside for this function out of the account pool, which is also its ceiling: invocations past it are throttled, not queued. Leave it unset for no reservation. 0 blocks every invocation.

    Caps the sandboxes, and so the downstream connections, a flood of invocations can open, and keeps that flood from starving other functions in the account. The Throttles alarm fires when the cap is hit.

    runtime?: Input<string>
    slowResponseAlarmThresholdMs?: number

    Handler duration in ms above which a SINGLE invocation raises an alarm.

    Opt-in, and deliberately so: this is a per-service response-time budget, not a fleet-wide health check. A function whose work is legitimately slow (a batch consumer, a report generator) has no such budget and should not carry the alarm — a threshold picked to fit everything fits nothing, gets muted, and a muted alarm is worse than none.

    Set it where a partner is waiting on the response. cfx-greendot-processor-api is the case this was built for: Green Dot's gateway holds the card authorisation open while we answer, so a slow answer is a failed authorisation long before it is a timeout.

    Alarms on Maximum, not an average or a percentile — the ask is "did ANY response exceed the budget", and an average over a low-traffic API hides exactly the one request that did. See slowResponseAlert.

    timeout?: Input<number>

    Amount of time your Lambda Function has to run in seconds. Valid between 1 and 900. Defaults to DEFAULT_TIMEOUT_SECONDS.

    usesIdempotencyTable?: boolean

    Whether this function uses the shared idempotency table. Set it wherever IDEMPOTENCY_TABLE_NAME appears in environment; omitting it grants no DynamoDB access.

    vpcId: Input<string>

    Networking and alerting inputs, as SCALARS.

    This component used to take a commonInfraStackRef and call requireOutput on it internally. That made the set of outputs it depended on invisible at every call site, and coupled ~20 lambda stacks to one stack's output names: when alarmTopicArn moved to cfx-ecs (now cfx-vpc) on 2026-08-03, every lambda deploy failed at once, in a file none of them mention. Passing values in makes the dependency visible and lets each stack source it from wherever that value now lives.

    warningAlarms?: { description: string; key: string; pattern: string }[]

    Log lines that should page, for a warning that only reaches CloudWatch.

    Sentry takes exceptions only, so a logger().warn has no alert unless one is declared here. Each entry becomes a metric filter and an alarm on this function's log group, routed to alarmTopicArn. pattern is a CloudWatch filter pattern; console.warn lines are plain text, so quote the message. key names the alarm and must be unique within the function.