Skip to main content

py-serverless-kit

Write your Python functions once. Deploy them to any of 10 clouds by changing one line of YAML.

py-serverless-kit (CLI: pskit) is a Serverless-Framework-style toolkit built on Terraform. Your handlers use one small, provider-neutral API (Event, Context, Response). A pskit.yml file says which cloud they run on and what triggers them: HTTP, schedules, queues, storage, topics. The same file can also define workflows in the style of Step Functions. pskit deploy generates Terraform for the chosen cloud, applies it, and builds an HTML dashboard of everything you deployed.

# app/handlers.py - identical on AWS, Azure, GCP, Alibaba, Oracle, IBM, DigitalOcean, Tencent, Huawei, Cloudflare
from py_serverless_kit import Event, Context, NotFound

def get_order(event: Event, ctx: Context):
    order = ORDERS.get(event.http.path_params["id"])
    if order is None:
        raise NotFound("no such order")      # -> HTTP 404 JSON on every cloud
    return order                              # -> HTTP 200 JSON
# pskit.yml
service: orders
provider:
  name: aws          # <- change to gcp, azure, alibaba, ... and redeploy. That's the migration.
  region: us-east-1
functions:
  get-order:
    handler: app.handlers.get_order
    events:
      - http: GET /orders/{id}
pskit deploy                      # terraform apply on AWS
pskit deploy --provider gcp       # same code, Google Cloud Functions
pskit dashboard --open            # every function, trigger, URL and resource id

Why

Teams that build on AWS Lambda and Step Functions end up with code full of API Gateway event parsing, SQS record loops and hand-written ASL. When the business needs another cloud, every function has to be rewritten. py-serverless-kit fixes this at both layers:

Layer Locked-in way With pskit
Handler code Parses event["requestContext"]["http"]["method"], Records[].body, ... Uses event.http.method, event.records[].body: the same on every cloud
Triggers / infra SAM / CloudFormation / console clicks One pskit.yml, rendered to Terraform for the target cloud
Workflows Step Functions ASL Portable state machine, compiled to Step Functions, Google Cloud Workflows, or run by the built-in engine everywhere else
Visibility One console per cloud One generated dashboard across all clouds and stages

Features

  • 10 providers: AWS Lambda, Azure Functions, Google Cloud Functions (gen2), Alibaba Function Compute, Oracle Functions, IBM Code Engine, DigitalOcean Functions, Tencent SCF, Huawei FunctionGraph, Cloudflare Workers.
  • Triggers: HTTP (path params, CORS, auth), schedules (rate/cron, translated into each cloud's cron dialect), queues, object storage, pub/sub topics, and direct function-to-function invoke().
  • Workflows: task / choice / wait / pass / parallel / map / succeed / fail with retry and catch. Native on AWS and GCP; an embedded engine on the other clouds; runnable locally with pskit workflow run.
  • Terraform underneath: real, reviewable main.tf.json, any backend (S3, GCS, azurerm, ...), works with OpenTofu. Escape hatches: terraform.extra, ${tf:...} references, per-function options.
  • Config that scales: extends:, per-provider providers: blocks, per-stage stages: blocks, and ${env:}, ${opt:}, ${self:}, ${file()} variables.
  • Local dev: pskit dev (hot-reloading HTTP server), pskit invoke with synthetic queue/storage/schedule events, and a LocalRunner for pytest.
  • Dashboard: a self-contained index.html listing every deployment, function, trigger, endpoint, ARN/id, console link and workflow.
  • Production details: deterministic artifacts (no redeploy when nothing changed), partial batch failures (BatchResult), structured JSON logs, consistent HTTP error mapping, stack traces hidden from clients, a stdlib-only runtime (no extra dependencies inside your function), and hooks (before_deploy, ...).

Supported providers

Provider Tier HTTP Schedule Queue Storage Topic Workflows
AWS Lambda stable ✅ ✅ ✅ SQS ✅ S3 ✅ SNS native (Step Functions)
Google Cloud Functions stable ✅ ✅ ✅ Pub/Sub ✅ GCS ✅ Pub/Sub native (Cloud Workflows)
Azure Functions stable ✅ ✅ ✅ Storage Queue ✅ Blob ✅ Service Bus embedded
Alibaba Function Compute beta ✅ ✅ – ✅ OSS ✅ MNS embedded
Huawei FunctionGraph beta ✅ ✅ – ✅ OBS ✅ SMN embedded
Tencent SCF beta ✅ ✅ – ✅ COS – embedded
DigitalOcean Functions beta ✅ ✅ – – – embedded
IBM Code Engine beta ✅ – – – – embedded
Oracle Cloud Functions experimental ✅ – – ✅ – embedded
Cloudflare Workers (Python) experimental ✅ ✅ – – – embedded

Run pskit providers for the live matrix. If a config uses a trigger the target cloud can't support, pskit validate fails with a clear message instead of deploying something half-working.

Maturity, honestly stated: the Terraform generated for every provider is checked with terraform validate against the real provider plugins (in CI, too). The stable providers cover the most surface area. beta and experimental providers follow vendor docs for event payloads that validate can't check, so try them on a non-production account first. See docs/providers.md for each provider's details and limits.

Install

pip install py-serverless-kit

You also need Terraform ≥ 1.5 (or OpenTofu) on your PATH, plus credentials for your cloud. See Getting started.

Quick start

pskit init my-api --provider aws --template full   # templates: http | events | workflow | full
cd my-api
pskit dev                                          # http://127.0.0.1:3000/hello
pskit invoke -f hello --path "/hello?name=Ada"
pskit workflow run order-pipeline -i '{"amount": 42}'
pskit deploy --stage dev
pskit info
pskit dashboard --open
pskit remove --stage dev

Move to another cloud

Change provider.name, or keep one file with per-cloud blocks:

provider:
  name: aws
  region: us-east-1
providers:              # applied only when that provider is selected
  gcp:   {region: europe-west1, options: {project: my-project}}
  azure: {region: westeurope, options: {subscription_id: "${env:ARM_SUBSCRIPTION_ID}"}}
pskit deploy --provider gcp
pskit deploy --provider azure --stage prod

Triggers at a glance

functions:
  api:
    handler: app.api.handle
    events:
      - http: {method: POST, path: /orders, cors: true}
      - http: GET /orders/{id}
  nightly:
    handler: app.jobs.nightly
    events:
      - schedule: {cron: "0 2 * * *", input: {report: daily}, timezone: Europe/Berlin}
  worker:
    handler: app.jobs.process
    timeout: 60
    events:
      - queue: {name: orders, batch_size: 10, dead_letter: orders-dlq}
  thumbnails:
    handler: app.media.on_upload
    events:
      - storage: {bucket: my-uploads-bucket, events: [created], suffix: .jpg}
  audit:
    handler: app.audit.on_event
    events:
      - topic: order-events
from py_serverless_kit import BatchResult, Event, Context

def process(event: Event, ctx: Context):
    result = BatchResult()               # retry only failed messages where the cloud supports it
    for record in event.records:
        try:
            handle(record.json())
        except Exception:
            result.fail(record)
    return result

Workflows (portable Step Functions)

workflows:
  order-pipeline:
    start_at: Validate
    states:
      Validate:
        type: task
        function: validate-order
        retry: [{errors: [TimeoutError], max_attempts: 3, backoff_rate: 2}]
        catch: [{errors: [ValueError], next: Rejected}]
        next: Route
      Route:
        type: choice
        choices: [{variable: "$.amount", gt: 1000, next: ManualReview}]
        default: Charge
      ManualReview: {type: wait, seconds: 3600, next: Charge}
      Charge: {type: task, function: charge-order, end: true}
      Rejected: {type: fail, error: OrderRejected}

The same definition becomes AWS Step Functions on AWS, Google Cloud Workflows on GCP, and an embedded orchestrator function on the other clouds. pskit workflow show order-pipeline --format asl prints the generated ASL.

How it works

 pskit.yml ──► config loader ──► provider validation ──► packager ──────────► artifact.zip
 (extends, providers:,          (capabilities,           (your code + stdlib-only
  stages:, ${vars})              limits, runtimes)        runtime + manifest + shim)
                                        │
                                        ▼
                              provider renderer ──► .pskit/<provider>-<stage>/main.tf.json
                                                              │ terraform init / apply
                                                              ▼
                                       deployment.json ──► dashboard/index.html

 At runtime:  cloud event ──► shim ──► runtime.adapters.<cloud> ──► Event ──► your handler
              your result ──► Response / raw value ──► adapter ──► native cloud response

More: docs/architecture.md.

Examples

Fifteen runnable scenarios live in examples/. They are tested in CI.

01-hello-http Minimal HTTP function
02-rest-api CRUD, path params, validation errors, CORS, cookies, binary, JWT
03-scheduled-jobs rate/cron schedules with input and time zones
04-queue-worker Queue consumer, partial batch failures, dead-letter queue
05-storage-events Object created/deleted with filters
06-pubsub-topic Topic fan-out and filters
07-workflow-orders Every workflow state type, retry/catch
08-multi-cloud Same code, all 10 providers
09-function-invoke Function-to-function invoke()
10-stages-and-config Stages, variables, secrets
11-custom-terraform terraform.extra, ${tf:...}, remote state, hooks
12-async-and-context async handlers, logging, deadlines
13-migrate-from-aws-lambda Before/after migration of Lambda + Step Functions
14-testing Unit-testing handlers and workflows with pytest
15-ci-cd-deploy GitHub Actions deploys per stage

Documentation

Getting started Install, credentials, first deploy
Configuration reference Every pskit.yml key, variables, extends, stages
Events HTTP, schedule, queue, storage, topic, with a per-provider matrix
Handler API Event, Context, Response, errors, BatchResult, invoke()
Workflows State machine reference, engines, limitations
Providers Options, credentials, resources and limits per cloud
CLI Every command and flag
Local development pskit dev, invoke, testing
Dashboard The deployment UI
Architecture Internals and third-party providers
Migrating from AWS Lambda + Step Functions → pskit
Troubleshooting Common errors and fixes

Contributing & releasing

Author

Created and maintained by Asif Khan @ Kavion.ai.

License

MIT, see LICENSE.

Metadata

Release files for py-serverless-kit 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for py-serverless-kit 0.1.0
File Size Uploaded
py_serverless_kit-0.1.0.tar.gz 232.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for py-serverless-kit 0.1.0
File Interpreter ABI Platform
py_serverless_kit-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 390.1 kB

Release files / py_serverless_kit-0.1.0.tar.gz

Download URL py_serverless_kit-0.1.0.tar.gz
Size 232.3 kB
Tags Source
SHA-256 checksum
How to use checksums
59bc6d360712107888335d83309d89135b51dd0f5c42230b0a37400ba60741cb
BLAKE2b-256 checksum
How to use checksums
cc1bda23b2c3d007a19acde6059c4ef997f0582a42cdb9fab85f6d2977c983da
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.10

Release files / py_serverless_kit-0.1.0-py3-none-any.whl

Download URL py_serverless_kit-0.1.0-py3-none-any.whl
Size 157.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
14e68627f23752aa8e91f51951910f6542edf7cf6bbbe5e993f2a5056a46d685
BLAKE2b-256 checksum
How to use checksums
cebf2bc059583a8546030670e4b269f382df726c686592f5b41d82e98868a4b5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.10

Release history Release notifications | RSS feed

0.1.1

2 release files

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page