Infrastructure,
Simplified.
Twelve focused .NET libraries that wrap AWS in clean, source-generated C# — every layer of a production service, from data to scheduling.
var order = await orders.FindOrderByCustomerAsync(id);order.Status = OrderStatus.Shipped;await orders.UpdateAsync(order);// Keys, GSIs, marshalling — derived from your POCOs.
Twelve libraries. One suite. Your AWS.
Type-safe NoSQL across DynamoDB, ScyllaDB, and Amazon Keyspaces — one [Repository] shape, three engines.
Learn more →Relational sibling with an Aurora DSQL provider. Same [Repository] ergonomics as NoSqlDatabase.
Learn more →Cache abstraction over DynamoDB, S3 Express, or in-memory — typed values, absolute expiry, namespaced keys.
Learn more →S3 wrapper with content-type detection, presigned URLs, and access levels.
Learn more →SQS wrapper — typed messages via IQueueManager, [QueueConsumer] batch handlers, retries, and automatic DLQ.
Learn more →[CloudFunctionHost] source-generated Lambda host — DI, config source, and cold-start reuse wired for you.
Learn more →ASP.NET Core baseline — BaseController Response<T> envelope, exception middleware, x-tenant-id resolution.
Learn more →Typed adapters for outbound HTTP APIs — auth, retries, and source-generated endpoints.
Learn more →First-party QR encoder with styled SVG/PNG rendering and a scannability verifier. AOT-clean.
Learn more →A queryable, DynamoDB-backed log store — write records into named groups, read them back by text and time.
Learn more →[Recurring(rate, unit)] on a method — a generated, drift-corrected recurring runner. Lambda, console, or hosted.
Learn more →In-process Extract → Transform → Load for bounded imports and migrations. CSV, JSON, DynamoDB extractors.
Learn more →Free Api & Queue are free under the Community license — individuals, open source, education, and companies under $250K.
Build with the same AWS services that run Airbnb, Nike, Zoom — and more.
Every Kanject Core library wraps a battle-tested AWS service running in production at the world's largest engineering teams. We give you the clean C# API. The infrastructure underneath is the same one those teams trust.
Stop writing boilerplate. Start shipping.
The same DynamoDB query — on the left, raw AWS SDK with manual credential wiring, expression attributes, and dictionary marshalling. On the right, idiomatic C# with Kanject.Core.NoSqlDatabase. Drag to compare.
You write this. We generate that.
Kanject.Core ships with Roslyn source generators and analyzers that turn a handful of attributes into a full, type-safe repository layer — compiled at build time. No reflection, no runtime surprises, no wrong-way-to-hold-it.
// <auto-generated> by Kanject DynamoDB Source Generator
#nullable enable
using System.Runtime.CompilerServices;
using Kanject.Core.Api.Abstractions.Models;
using Kanject.Core.NoSqlDatabase.Provider.DynamoDb.Abstractions.Extensions;
using Kanject.Core.NoSqlDatabase.Provider.DynamoDb.Abstractions.Interfaces;
using Kanject.Core.NoSqlDatabase.Provider.DynamoDb.Abstractions.Models;
using Kanject.Core.NoSqlDatabase.Provider.DynamoDbV2;
using Demo.Marketplace.Data.DbContexts;
using Demo.Marketplace.Data.Entities.SellerSettings;
namespace Demo.Marketplace.Data.Repositories;
public record struct SellerSettingRepositoryItemCollection(
SellerSettingEntity? SellerSetting,
SellerBundleDiscountSettingEntity? SellerBundleDiscountSetting);
public enum SellerSettingRepositoryItemCollectionType
{
SellerSetting = 0,
SellerBundleDiscountSetting = 1,
}
public partial class SellerSettingRepository
: Repository<SellerSettingEntity>
{
public SellerSettingRepository() {}
public SellerSettingRepository(MarketplaceDbContext dbContext)
: base(dbContext)
{
SetUnitOfWork(new UnitOfWork(dbContext));
}
protected QueryConfig QueryConfigInstance
{
get
{
var queryConfig = new QueryConfig { TableName = CurrentTableName };
if (DbContext is not IDynamoDbContext dbContext)
return queryConfig;
if (dbContext.ModelBuilder?.PartitionKey is not null)
queryConfig.AddPartitionKey(dbContext.ModelBuilder.PartitionKey);
if (dbContext.ModelBuilder?.SortKey is not null)
queryConfig.AddSortKey(dbContext.ModelBuilder.SortKey);
return queryConfig;
}
}
public void BeginTransaction() => UnitOfWork.BeginTransaction();
public Task CommitAsync(CancellationToken? cancellationToken = null)
=> UnitOfWork.TransactionExpressions.Count > 0
? UnitOfWork.CommitAsync(cancellationToken)
: Task.CompletedTask;
private SellerSettingRepositorySellerBundleDiscountSettingEntityRepository?
_sellerBundleDiscountSetting;
public SellerSettingRepositorySellerBundleDiscountSettingEntityRepository
SellerBundleDiscountSetting
{
get
{
_sellerBundleDiscountSetting ??= DbContext is not null
? new SellerSettingRepositorySellerBundleDiscountSettingEntityRepository(
Unsafe.As<MarketplaceDbContext>(DbContext))
: new SellerSettingRepositorySellerBundleDiscountSettingEntityRepository();
if (UnitOfWork is not null)
_sellerBundleDiscountSetting.SetUnitOfWork(UnitOfWork);
return _sellerBundleDiscountSetting;
}
}
public Task<SellerSettingEntity?> FindSellerSettingAsync(
Guid sellerUserId,
bool isConsistentRead = true,
QueryConfig? queryConfig = null)
{
queryConfig ??= QueryConfigInstance;
queryConfig.AddPartitionKeyValue(
SellerSettingEntityKeys.ComposeSellerSettingPartitionKey(sellerUserId));
queryConfig.AddSortKeyValue(
DbFunc.Equals(SellerSettingEntityKeys.ComposeSellerSettingSortKey()));
return GetSingleAsync(
queryConfig.ReturnEventualConsistentData(!isConsistentRead));
}
// + 1,100 lines: typed overloads, update/insert helpers,
// entity-repository methods, key composers, checks, and DI registration.
}Every build emits a manual.
Every Kanject Core library writes a comprehensive Markdown spec at compile time — generated repositories, key templates, indexes, queues, event topics, cache contexts. The same source-generator pass that emits typed C# also emits the README, in full. Drop the file straight into your AI assistant for instant, accurate codebase context.
using Amazon.DynamoDBv2.DataModel;using Kanject.Core.NoSqlDatabase.Provider.DynamoDb.Annotations.Attributes;using Demo.Marketplace.Data.DbContexts;[DbContext][EnableRecordLifeTimeSupport]public partial class MarketplaceDbContext;public record SellerSettingEntity : AbstractBaseEntity{ [KeyTemplate("SellerSettings#{SellerUserId}")] [DynamoDBHashKey("pk")] public override string PartitionKey { get; set; } = string.Empty; [KeyTemplate("Info")] [DynamoDBRangeKey("sk")] public override string SortKey { get; set; } = string.Empty; [DynamoDBProperty] public Guid SellerUserId { get; set; } [DynamoDBProperty] public HolidayModeStatus HolidayModeStatus { get; set; }}[Repository(Entity = typeof(SellerSettingEntity), Version = 2)][DbContext(typeof(MarketplaceDbContext))][EntityRepository(typeof(SellerBundleDiscountSettingEntity), IsMultipleCollectionItem = false)]public partial class SellerSettingRepository; Demo.Marketplace.Data — DynamoDB Schema Reference
| Database Contexts | 1 |
| Repositories | 13 |
| Global Secondary Indexes | 1 |
| Expiring Records | 3 |
| Embedded Repositories | 7 |
| Unique Entities | 22 |
| Key Templates | 46 |
| Kanject Indexes | 24 |
- Quick Overview
- Core Concepts & Glossary
- Common Tasks
- Constraints & Invariants
- Do / Don't Guidance
- Generated vs. Handwritten Code
- Single Table Key Design
- Repositories 13
- Global Secondary Indexes
- Expiring Records
- Capacity & Throughput
- WCU/RCU Cost per Access Pattern
- CloudWatch Alarm Recommendations
- Security Posture & IAM Actions
- Method Quick Reference
- … 13 more sections
Your first package is free. The suite is one license away.
Api and the base Queue are Community packages — pull them from public NuGet and start building today. The paid libraries ship from a private feed: license the suite, and one sign-in with the free CLI connects it for your machine, your teammates, and your CI. Deploying with the CLI stays entirely optional.
Ship faster, with fewer mistakes.
Core gives you the primitives to build all of this yourself. Kanject BaaS is optional — auth, wallet, notifications, analytics and more, pre-assembled and hardened in your own AWS, for when you'd rather move faster than rebuild a ledger or an identity layer from scratch.
See your data layer, visually.
Paste your annotated POCOs and DynoStudio derives the tables, the indexes, and the typed query functions — then lets you browse and query without leaving the studio. The same surface drives every Kanject demo call.
From the team — building Kanject Core.
Parallel.ForEachAsync wasn't enough. So we built our own.
The four things every batched-I/O workload needs — scoped DI, retry policy, per-partition timeout, and partial-batch acknowledgement — none of which the BCL gives you in one place. Here's why we shipped Kanject.Core.Parallel.
How we ship source generators that survive refactors
Lessons from two years of building Roslyn generators that don't silently break when downstream code moves.
Cadence belongs on the method, not in startup
Why we built drift-corrected, attribute-driven recurring tasks with three call-site overloads — and why we don't think you should reach for Timer, PeriodicTimer, or BackgroundService directly anymore.
Simplify your cloud
journey today.
Join forward-thinking developers and businesses who trust Kanject to eliminate cloud complexity and accelerate innovation.